diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 93203a05559..d058cdc0438 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -459,7 +459,6 @@ src << "Your spine still aches!" return - if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) src << "You cannot launch a quill in your current state." return @@ -473,3 +472,91 @@ var/obj/item/weapon/arrow/quill/A = new /obj/item/weapon/arrow/quill(usr.loc) A.throw_at(target, 10, 30, user) msg_admin_attack("[key_name_admin(src)] launched a quill at [key_name_admin(target)] (JMP)",ckey=key_name(src),ckey_target=key_name(target)) + + +/mob/living/carbon/human/proc/shatter_light() + set category = "Abilities" + set name = "Shatter Lights" + set desc = "Shatter all lights around yourself." + + if(last_special > world.time) + src << "You're still regaining your strength!" + return + + last_special = world.time + 50 + + visible_message("\The [src] shrieks!") + playsound(src.loc, 'sound/species/shadow/grue_screech.ogg', 100, 1) + + for(var/obj/machinery/light/L in range(7)) + L.broken() + +/mob/living/carbon/human/proc/create_darkness() + set category = "Abilities" + set name = "Create Darkness" + set desc = "Create a field of darkness around yourself." + + if(last_special > world.time) + src << "You're still regaining your strength!" + return + + last_special = world.time + 100 + + playsound(src.loc, 'sound/species/shadow/grue_growl.ogg', 100, 1) + + src.set_light(4,-20) + + addtimer(CALLBACK(src, /atom/.proc/set_light, 0), 30 SECONDS) + +/mob/living/carbon/human/proc/darkness_eyes() + set category = "Abilities" + set name = "Toggle Shadow Vision" + set desc = "Toggle between seeing shadows or not." + + if (!stop_sight_update) + src << "Your eyes shift around, allowing you to see in the dark." + src.stop_sight_update = 1 + src.see_invisible = SEE_INVISIBLE_NOLIGHTING + + else + src << "You return your vision to normal." + src.stop_sight_update = 0 + +/mob/living/carbon/human/proc/shadow_step(var/turf/T in turfs) + set category = "Abilities" + set name = "Shadow Step" + set desc = "Travel from place to place using the shadows." + + if(last_special > world.time) + src << "You're still regaining your strength!" + return + + if (!T || T.density || T.contains_dense_objects()) + src << "You cannot do that." + return + + if(!isturf(loc)) + to_chat(src, "You cannot teleport out of your current location.") + return + + if (T.z != src.z || get_dist(T, get_turf(src)) > world.view) + src << "Your powers are not capable of taking you that far." + return + + if (!T.dynamic_lighting || T.get_lumcount() > 0.1) + src << "The destination is too bright." + return + + last_special = world.time + 200 + + visible_message("\The [src] vanishes into the shadows!") + + anim(get_turf(loc), loc,'icons/mob/mob.dmi',,"shadow", null ,loc.dir) + + forceMove(T) + + for (var/obj/item/weapon/grab/G in contents) + if (G.affecting) + G.affecting.forceMove(locate(T.x + rand(-1,1), T.y + rand(-1,1), T.z)) + else + qdel(G) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 848f985e61c..fd28ae6b76e 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -920,6 +920,15 @@ if(status_flags & GODMODE) return 0 //godmode + if(species.light_dam) + var/light_amount = 0 + if(isturf(loc)) + var/turf/T = loc + light_amount = T.get_lumcount() * 10 + if(light_amount > species.light_dam) //if there's enough light, start dying + take_overall_damage(5,5) + else //heal in the dark + heal_overall_damage(5,5) // nutrition decrease if (nutrition > 0 && stat != 2) diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm index 59518009af0..2f6251dba27 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm @@ -1,13 +1,25 @@ +/mob/living/carbon/human/shadow/Initialize(mapload) + . = ..(mapload, "Shadow") + /datum/species/shadow name = "Shadow" name_plural = "shadows" + blurb = "Have you ever been alone at night \ + thought you heard footsteps behind, \ + and turned around and no one's there? \ + And as you quicken up your pace \ + you find it hard to look again, \ + because you're sure there's someone there." + icobase = 'icons/mob/human_races/r_shadow.dmi' deform = 'icons/mob/human_races/r_shadow.dmi' - eyes = "blank_eyes" + eyes = "eyes_shadow" + has_floating_eyes = 1 - language = "Sol Common" //todo? - unarmed_types = list(/datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/sharp) + language = "Cult" + + unarmed_types = list(/datum/unarmed_attack/bite/sharp, /datum/unarmed_attack/claws/strong) light_dam = 2 darksight = 8 has_organ = list() @@ -15,23 +27,78 @@ rarity_value = 10 virus_immune = 1 + breakcuffs = list(MALE,FEMALE,NEUTER) + fall_mod = 0 + ethanol_resistance = -1 + taste_sensitivity = TASTE_NUMB + + speech_sounds = list('sound/species/shadow/grue_growl.ogg') + speech_chance = 50 + + warning_low_pressure = 50 //immune to pressure, so they can into space/survive breaches without worries + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + brute_mod = 0.5 + burn_mod = 1.2 + + breath_type = null + poison_type = null + blood_color = "#CCCCCC" flesh_color = "#AAAAAA" remains_type = /obj/effect/decal/cleanable/ash death_message = "dissolves into ash..." - flags = NO_BLOOD | NO_SCAN | NO_SLIP | NO_POISON | NO_MINOR_CUT + flags = NO_BLOOD | NO_SCAN | NO_SLIP | NO_POISON | NO_PAIN | NO_BREATHE | NO_MINOR_CUT spawn_flags = IS_RESTRICTED + vision_flags = DEFAULT_SIGHT | SEE_MOBS + + has_limbs = list( + "chest" = list("path" = /obj/item/organ/external/chest/unbreakable), + "groin" = list("path" = /obj/item/organ/external/groin/unbreakable), + "head" = list("path" = /obj/item/organ/external/head/unbreakable), + "l_arm" = list("path" = /obj/item/organ/external/arm/unbreakable), + "r_arm" = list("path" = /obj/item/organ/external/arm/right/unbreakable), + "l_leg" = list("path" = /obj/item/organ/external/leg/unbreakable), + "r_leg" = list("path" = /obj/item/organ/external/leg/right/unbreakable), + "l_hand" = list("path" = /obj/item/organ/external/hand/unbreakable), + "r_hand" = list("path" = /obj/item/organ/external/hand/right/unbreakable), + "l_foot" = list("path" = /obj/item/organ/external/foot/unbreakable), + "r_foot" = list("path" = /obj/item/organ/external/foot/right/unbreakable) + ) + stamina = 500 //Tireless automatons stamina_recovery = 1 sprint_speed_factor = 0.3 exhaust_threshold = 0 //No oxyloss, so zero threshold + inherent_verbs = list( + /mob/living/carbon/human/proc/shatter_light, + /mob/living/carbon/human/proc/create_darkness, + /mob/living/carbon/human/proc/darkness_eyes, + /mob/living/carbon/human/proc/shadow_step + ) + /datum/species/shadow/handle_death(var/mob/living/carbon/human/H) spawn(1) new /obj/effect/decal/cleanable/ash(H.loc) qdel(H) + +/datum/species/shadow/handle_post_spawn(var/mob/living/carbon/human/H) + if(H.mind) + H.mind.assigned_role = "Shadow" + H.mind.special_role = "Shadow" + H.real_name = "grue" + H.name = H.real_name + ..() + +/datum/species/shadow/get_random_name() + return "grue" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index d0be291aed3..ebe84ee1513 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -379,7 +379,7 @@ There are several things that need to be remembered: var/has_visible_hair = h_style && !(head && (head.flags_inv & BLOCKHEADHAIR)) var/icon/hair_icon = generate_hair_icon(has_visible_hair) - + // Handle light emission. if (species.light_range) if (has_visible_hair) @@ -398,7 +398,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_mutations(var/update_icons=1) if (QDELING(src)) return - + var/fat if(FAT in mutations) fat = "fat" @@ -447,7 +447,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/regenerate_icons() if (QDELING(src)) return - + ..() if(transforming) return @@ -484,7 +484,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) if (QDELING(src)) return - + overlays_raw[UNIFORM_LAYER] = null if(check_draw_underclothing()) w_uniform.screen_loc = ui_iclothing @@ -550,7 +550,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) if (QDELING(src)) return - + overlays_raw[ID_LAYER] = null if(wear_id) @@ -571,8 +571,8 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_gloves(var/update_icons=1) if (QDELING(src)) return - - + + if(check_draw_gloves()) var/t_state = gloves.item_state || gloves.icon_state @@ -682,7 +682,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_shoes(var/update_icons=1) if (QDELING(src)) return - + overlays_raw[SHOES_LAYER] = null if(check_draw_shoes()) var/image/standing @@ -721,7 +721,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_s_store(var/update_icons=1) if (QDELING(src)) return - + if(s_store) //s_store.auto_adapt_species(src) overlays_raw[SUIT_STORE_LAYER] = image('icons/mob/belt_mirror.dmi', s_store.item_state || s_store.icon_state) @@ -839,7 +839,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) if (QDELING(src)) return - + if (istype(wear_suit, /obj/item)) wear_suit.screen_loc = ui_oclothing @@ -892,7 +892,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_pockets(var/update_icons=1) if (QDELING(src)) return - + if(l_store) l_store.screen_loc = ui_storage1 //TODO if(r_store) @@ -1002,7 +1002,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) if (QDELING(src)) return - + if(handcuffed) drop_r_hand() drop_l_hand() @@ -1025,7 +1025,7 @@ There are several things that need to be remembered: /mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) if (QDELING(src)) return - + if(legcuffed) var/image/standing if(legcuffed.icon_override) @@ -1081,7 +1081,7 @@ There are several things that need to be remembered: overlays_raw[R_HAND_LAYER] = image(t_icon, t_state) - if(update_icons) + if(update_icons) update_icons() diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 88bcbe64136..6b96c97bb6c 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -174,8 +174,9 @@ if (is_ventcrawling) sight |= SEE_TURFS|BLIND - see_in_dark = initial(see_in_dark) - see_invisible = initial(see_invisible) + if (!stop_sight_update) //If true, it won't reset the mob vision flags to the initial ones + see_in_dark = initial(see_in_dark) + see_invisible = initial(see_invisible) /mob/living/proc/update_dead_sight() sight |= SEE_TURFS diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index ad3c55627c6..072bbe983ff 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -72,3 +72,5 @@ var/cloaked = 0//Set to 1 by cloaking devices, optimises update_icons var/tesla_ignore = 0 // If true, mob is not affected by tesla bolts. + + var/stop_sight_update = 0 //If true, it won't reset the mob vision flags diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index ebdd7b40bba..1822e2ad4c5 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/sound/species/shadow/grue_ambience.ogg b/sound/species/shadow/grue_ambience.ogg new file mode 100644 index 00000000000..2b84ea0f4bc Binary files /dev/null and b/sound/species/shadow/grue_ambience.ogg differ diff --git a/sound/species/shadow/grue_growl.ogg b/sound/species/shadow/grue_growl.ogg new file mode 100644 index 00000000000..64cde513c13 Binary files /dev/null and b/sound/species/shadow/grue_growl.ogg differ diff --git a/sound/species/shadow/grue_screech.ogg b/sound/species/shadow/grue_screech.ogg new file mode 100644 index 00000000000..c79f26bb186 Binary files /dev/null and b/sound/species/shadow/grue_screech.ogg differ