diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm index ecc3ca077e5..8f702cd4124 100644 --- a/code/_onclick/hud/spell_screen_objects.dm +++ b/code/_onclick/hud/spell_screen_objects.dm @@ -218,3 +218,12 @@ spell.perform(usr) update_charge(1) + + + +//Xenochimera, literally just different icons +/obj/screen/movable/spell_master/chimera + name = "Chimera Abilities" + icon_state = "cult_spell_ready" + open_state = "genetics_open" + closed_state = "genetics_closed" diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index f45f31eb34a..7a771e7b231 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -177,6 +177,7 @@ var/has_glowing_eyes = 0 // Whether the eyes are shown above all lighting var/water_movement = 0 // How much faster or slower the species is in water var/snow_movement = 0 // How much faster or slower the species is on snow + var/infect_wounds = 0 // Whether the species can infect wounds, only works with claws / bites var/item_slowdown_mod = 1 // How affected by item slowdown the species is. @@ -419,7 +420,6 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list( for(var/spell_to_add in inherent_spells) var/spell/S = new spell_to_add(H) H.add_spell(S) - return /datum/species/proc/remove_inherent_spells(var/mob/living/carbon/human/H) H.spellremove() diff --git a/code/modules/mob/living/carbon/human/species/station/station_special.dm b/code/modules/mob/living/carbon/human/species/station/station_special.dm index 424fe34efc5..e7ec0c509df 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special.dm @@ -26,7 +26,6 @@ tail = "tail" //Scree's tail. Can be disabled in the vore tab by choosing "hide species specific tail sprite" icobase_tail = 1 inherent_verbs = list( - /mob/living/carbon/human/proc/reconstitute_form, /mob/living/carbon/human/proc/sonar_ping, /mob/living/carbon/human/proc/succubus_drain, /mob/living/carbon/human/proc/succubus_drain_finalize, @@ -40,7 +39,7 @@ /mob/living/proc/eat_trash, /mob/living/proc/glow_toggle, /mob/living/proc/glow_color, - /mob/living/carbon/human/proc/lick_wounds , + /mob/living/carbon/human/proc/lick_wounds, /mob/living/carbon/human/proc/resp_biomorph, /mob/living/carbon/human/proc/biothermic_adapt, /mob/living/carbon/human/proc/atmos_biomorph, @@ -53,18 +52,24 @@ /mob/living/carbon/human/proc/shapeshifter_select_wings, /mob/living/carbon/human/proc/shapeshifter_select_tail, /mob/living/carbon/human/proc/shapeshifter_select_ears, - /mob/living/carbon/human/proc/regenerate, - /mob/living/carbon/human/proc/commune) //Xenochimera get all the special verbs since they can't select traits. + /mob/living/carbon/human/proc/shapeshifter_select_shape, + /mob/living/carbon/human/proc/commune + ) //Xenochimera get all the special verbs since they can't select traits. inherent_spells = list( /spell/targeted/chimera/thermal_sight, - /spell/targeted/chimera/voice_mimic + /spell/targeted/chimera/voice_mimic, + /spell/targeted/chimera/regenerate, + /spell/targeted/chimera/hatch, + /spell/targeted/chimera/no_breathe ) - var/feral_spells = list( + var/list/feral_spells = list( /spell/aoe_turf/dissonant_shriek ) + var/list/removable_spells = list() + var/has_feral_spells = FALSE virus_immune = 1 // They practically ARE one. min_age = 18 @@ -112,7 +117,7 @@ "Akula","Nevrean","Highlander Zorren", "Flatland Zorren", "Vulpkanin", "Vasilissan", "Rapala", "Neaera", "Stok", "Farwa", "Sobaka", - "Wolpin", "Saru", "Sparra") + "Wolpin", "Saru", "Sparra", "Vox") //primitive_form = "Farwa" @@ -133,6 +138,7 @@ ) heal_rate = 0.5 + infect_wounds = 1 flesh_color = "#AFA59E" base_color = "#333333" blood_color = "#14AD8B" @@ -168,19 +174,47 @@ H.eye_blurry = max(5,H.eye_blurry) ..() +/datum/species/shapeshifter/xenochimera/add_inherent_spells(var/mob/living/carbon/human/H) + var/master_type = /obj/screen/movable/spell_master/chimera + var/obj/screen/movable/spell_master/chimera/new_spell_master = new master_type + + if(!H.spell_masters) + H.spell_masters = list() + + if(H.client) + H.client.screen += new_spell_master + new_spell_master.spell_holder = H + H.spell_masters.Add(new_spell_master) + + for(var/spell_to_add in inherent_spells) + var/spell/S = new spell_to_add(H) + H.add_spell(S, "cult", master_type) + /datum/species/shapeshifter/xenochimera/proc/add_feral_spells(var/mob/living/carbon/human/H) - if(!has_feral_spells && LAZYLEN(feral_spells) > 0) - has_feral_spells = TRUE - for(var/spell_to_add in feral_spells) - var/spell/S = new spell_to_add(H) - H.add_spell(S) + if(!has_feral_spells) + var/check = FALSE + var/master_type = /obj/screen/movable/spell_master/chimera + for(var/spell/S as anything in feral_spells) + var/spell/spell_to_add = new S(H) + check = H.add_spell(spell_to_add, "cult", master_type) + removable_spells += spell_to_add + if(check) + has_feral_spells = TRUE + else + return else return /datum/species/shapeshifter/xenochimera/proc/remove_feral_spells(var/mob/living/carbon/human/H) - H.spellremove() //This removes ALL spells + for(var/spell/S as anything in removable_spells) + S.remove_self(H) + removable_spells.Cut() has_feral_spells = FALSE - addtimer(CALLBACK(src, .proc/add_inherent_spells,H), 1 SECOND, TIMER_UNIQUE) //This doesn't work well without a delay, crappy workaround. Resets all cooldowns, too. + +/datum/species/shapeshifter/xenochimera/handle_post_spawn(mob/living/carbon/human/H) + ..() + for(var/spell/S as anything in feral_spells) + S = new S(H) /datum/species/shapeshifter/xenochimera/proc/handle_feralness(var/mob/living/carbon/human/H) @@ -452,7 +486,7 @@ /mob/living/carbon/human/proc/resp_biomorph(mob/living/carbon/human/target in view(1)) set name = "Respiratory Biomorph" set desc = "Changes the gases we need to breathe." - set category = "Abilities" + set category = "Chimera" var/list/gas_choices = list( "oxygen" = /datum/gas/oxygen, @@ -505,7 +539,7 @@ /mob/living/carbon/human/proc/biothermic_adapt(mob/living/carbon/human/target in view(1)) set name = "Biothermic Adaptation" set desc = "Changes our core body temperature." - set category = "Abilities" + set category = "Chimera" var/list/temperature_options = list( "warm-blooded", @@ -599,7 +633,7 @@ /mob/living/carbon/human/proc/atmos_biomorph(mob/living/carbon/human/target in view(1)) set name = "Atmospheric Biomorph" set desc = "Changes our sensitivity to atmospheric pressure." - set category = "Abilities" + set category = "Chimera" var/list/pressure_options = list( @@ -649,7 +683,7 @@ /mob/living/carbon/human/proc/vocal_biomorph() set name = "Vocalization Biomorph" set desc = "Changes our speech pattern." - set category = "Abilities" + set category = "Chimera" var/vocal_biomorph = input(src, "How should we adjust our speech?") as null|anything in list("common", "unathi", "tajaran") if(!vocal_biomorph) diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index de98dab237b..ee47dc6abd4 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -10,6 +10,7 @@ var/global/list/sparring_attack_cache = list() var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent. var/sharp = 0 var/edge = 0 + var/infected_wound_probability = 10 var/damage_type = BRUTE var/sparring_variant_type = /datum/unarmed_attack/light_strike @@ -89,6 +90,30 @@ var/global/list/sparring_attack_cache = list() target.visible_message("[target] has been weakened!") target.apply_effect(3, WEAKEN, armour) + if(user.species.infect_wounds) //Creates a pre-damaged, pre-infected wound. As nasty as this code. + if(prob(infected_wound_probability)) + var/obj/item/organ/external/affecting = target.get_organ(zone) + var/attack_message + var/datum/wound/W + if(edge) + W = new /datum/wound/cut/small(5) + W.force_infect() + attack_message = "leaves behind infested residue in [target]!" + else + W = new /datum/wound/bruise(5) + W.force_infect() + attack_message = "scratches and pummels, their infested fluids mixing with [target]!" + if(LAZYLEN(affecting.wounds)) + for(var/datum/wound/other in affecting.wounds) + if(other.can_merge(W)) + other.merge_wound(W) + W = null + break + if(W) + affecting.wounds += W + + target.visible_message("[user] [attack_message]") + /datum/unarmed_attack/proc/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage) var/obj/item/organ/external/affecting = target.get_organ(zone) user.visible_message("[user] [pick(attack_verb)] [target] in the [affecting.name]!") diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm index dd7f5dcf890..cc91debbfff 100644 --- a/code/modules/organs/wound.dm +++ b/code/modules/organs/wound.dm @@ -19,11 +19,11 @@ var/min_damage = 0 // is the wound bandaged? - var/bandaged = 0 + var/bandaged = FALSE // Similar to bandaged, but works differently - var/clamped = 0 + var/clamped = FALSE // is the wound salved? - var/salved = 0 + var/salved = FALSE // is the wound disinfected? var/disinfected = 0 var/created = 0 @@ -37,7 +37,7 @@ // stages such as "cut", "deep cut", etc. var/list/stages // internal wounds can only be fixed through surgery - var/internal = 0 + var/internal = FALSE // maximum stage at which bleeding should still happen. Beyond this stage bleeding is prevented. var/max_bleeding_stage = 0 // one of CUT, PIERCE, BRUISE, BURN @@ -46,7 +46,8 @@ // the maximum amount of damage that this wound can have and still autoheal var/autoheal_cutoff = 10 - + // whether this wound starts infected regardless of damage level + var/forced_infected = FALSE // helper lists @@ -119,19 +120,29 @@ src.germ_level = max(src.germ_level, other.germ_level) src.created = max(src.created, other.created) //take the newer created time + //forces an infection, and bleeding regardless of damage or stage + proc/force_infect() + bleed_threshold = 4 //Will always start bleeding, making the infection worse if untreated + forced_infected = TRUE + germ_level = INFECTION_LEVEL_ONE + 1 // checks if wound is considered open for external infections // untreated cuts (and bleeding bruises) and burns are possibly infectable, chance higher if wound is bigger proc/infection_check() - if (damage < 10) //small cuts, tiny bruises, and moderate burns shouldn't be infectable. - return 0 - if (is_treated() && damage < 25) //anything less than a flesh wound (or equivalent) isn't infectable if treated properly - return 0 if (disinfected) - germ_level = 0 //reset this, just in case - return 0 - + if(germ_level > INFECTION_LEVEL_ONE) + germ_level = 0 //reset this, just in case + forced_infected = FALSE + return FALSE + if (damage < 10 && !forced_infected) //small cuts, tiny bruises, and moderate burns shouldn't be infectable. + return FALSE + if (is_treated() && damage < 25) //anything less than a flesh wound (or equivalent) isn't infectable if treated properly + return FALSE if (damage_type == BRUISE && !bleeding()) //bruises only infectable if bleeding - return 0 + return FALSE + + + if(forced_infected) //This wound is forced to be infected, circumventing damage requirements, check after making sure it's not bleeding and isn't disinfected + return TRUE var/dam_coef = round(damage/10) switch (damage_type) @@ -142,7 +153,7 @@ if (CUT) return prob(dam_coef*20) - return 0 + return FALSE proc/bandage() bandaged = 1 @@ -295,7 +306,7 @@ max_bleeding_stage = 3 stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large blood soaked clot" = 25, "large angry scar" = 10, "large straight scar" = 0) -datum/wound/cut/massive +/datum/wound/cut/massive max_bleeding_stage = 3 stages = list("massive wound" = 70, "massive healing wound" = 50, "massive blood soaked clot" = 25, "massive angry scar" = 10, "massive jagged scar" = 0) @@ -365,7 +376,7 @@ datum/wound/puncture/massive /** INTERNAL BLEEDING **/ /datum/wound/internal_bleeding - internal = 1 + internal = TRUE stages = list("severed artery" = 30, "cut artery" = 20, "damaged artery" = 10, "bruised artery" = 5) autoheal_cutoff = 5 max_bleeding_stage = 4 //all stages bleed. It's called internal bleeding after all. @@ -399,4 +410,4 @@ datum/wound/puncture/massive ..(damage_amt) /datum/wound/lost_limb/can_merge(var/datum/wound/other) - return 0 //cannot be merged + return FALSE //cannot be merged diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm index 31397c6cd0d..4ab16b6df24 100644 --- a/code/modules/spells/spell_code.dm +++ b/code/modules/spells/spell_code.dm @@ -340,3 +340,6 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now if(!user || (!(spell_flags & (STATALLOWED|GHOSTCAST)) && user.stat != originalstat) || !(user.loc == Location)) return 0 return 1 + +/spell/proc/remove_self(mob/user = usr) + user.remove_spell(src) diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm index f98eba16786..850e90ca0e4 100644 --- a/code/modules/spells/spells.dm +++ b/code/modules/spells/spells.dm @@ -36,7 +36,6 @@ /mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready", var/master_type = /obj/screen/movable/spell_master) if(!spell_masters) spell_masters = list() - if(spell_masters.len) for(var/obj/screen/movable/spell_master/spell_master in spell_masters) if(spell_master.type == master_type) diff --git a/code/modules/spells/targeted/chimera_spells.dm b/code/modules/spells/targeted/chimera_spells.dm index ff4cbf0e1ec..79b34831105 100644 --- a/code/modules/spells/targeted/chimera_spells.dm +++ b/code/modules/spells/targeted/chimera_spells.dm @@ -15,19 +15,24 @@ duration = 0 hud_state = "wiz_jaunt" + override_base = "cult" var/nutrition_cost_minimum = 50 var/nutrition_cost_proportional = 20 //percentage of nutriment it should cost if it's higher than the minimum /spell/targeted/chimera/cast(list/targets, mob/user) if(ishuman(user)) var/mob/living/carbon/human/H = user - var/nut = H.nutrition / nutrition_cost_proportional + var/nut = (H.nutrition * nutrition_cost_proportional) / 100 var/final_cost if(nut > nutrition_cost_minimum) final_cost = nut else final_cost = nutrition_cost_minimum - H.nutrition -= final_cost + + if((H.nutrition - final_cost) >= 0) + H.nutrition -= final_cost + else + H.nutrition = 0 //We're already super starved, and feral, so cast it for free, you're likely using it to get food at this point. else return @@ -45,7 +50,7 @@ invocation_type = SpI_NONE charge_max = 35 SECONDS duration = 30 SECONDS - nutrition_cost_minimum = 100 + nutrition_cost_minimum = 15 //The hungrier you get the less it will cost nutrition_cost_proportional = 10 var/active = FALSE @@ -71,7 +76,7 @@ /////////////// //Voice Mimic// /////////////// - +//It's a toggle, but doesn't cost nutriment to be toggled off /spell/targeted/chimera/voice_mimic name = "Voice Mimicry" desc = "We shape our throat and tongue to imitate a person, or a sound. This ability is a toggle." @@ -80,10 +85,10 @@ hud_state = "ling_mimic_voice" invocation = "none" invocation_type = SpI_NONE - charge_max = 10 SECONDS + charge_max = 5 SECONDS duration = 0 - nutrition_cost_minimum = 100 - nutrition_cost_proportional = 15 + nutrition_cost_minimum = 25 + nutrition_cost_proportional = 5 var/active = FALSE /spell/targeted/chimera/voice_mimic/cast(list/targets, mob/user = usr) @@ -98,7 +103,7 @@ to_chat(user, "We shift and morph our tongues, ready to reverberate as: [mimic_voice].") H.SetSpecialVoice(mimic_voice) active = TRUE - ..() + ..() //Processes nutriment cost else to_chat(user, "We return our voice to our normal identity.") H.UnsetSpecialVoice() @@ -107,6 +112,211 @@ return +//////////////// +//Regeneration// +//////////////// +//Huge cooldown, huge cost, but will actually heal most of your issues. + +/spell/targeted/chimera/regenerate + name = "Regeneration" + desc = "We shed our skin, purging it of damage, regrowing limbs." + + spell_flags = INCLUDEUSER + hud_state = "ling_fleshmend" + invocation = "none" + invocation_type = SpI_NONE + charge_max = 10 MINUTES + duration = 0 + nutrition_cost_minimum = 500 + nutrition_cost_proportional = 75 + var/healing_amount = 30 + var/delay = 2 MINUTES + + +/spell/targeted/chimera/regenerate/cast_check(skipcharge = 0,mob/user = usr) + if(..()) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if((nutrition_cost_minimum > H.nutrition) || nutrition_cost_minimum > ((H.nutrition * nutrition_cost_proportional) / 100) ) + to_chat(H,"We don't have enough nutriment. This ability is costly...") + return FALSE + else return TRUE + +/spell/targeted/chimera/regenerate/cast(list/targets, mob/user = usr) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(do_after(H, delay, null, FALSE, TRUE, INCAPACITATION_DISABLED)) + H.restore_blood() + H.species.create_organs(H) + H.restore_all_organs() + H.adjustBruteLoss(-healing_amount) + H.adjustFireLoss(-healing_amount) + H.adjustOxyLoss(-healing_amount) + H.adjustCloneLoss(-healing_amount) + H.adjustBrainLoss(-healing_amount) + H.blinded = 0 + H.SetBlinded(0) + H.eye_blurry = 0 + H.ear_deaf = 0 + H.ear_damage = 0 + + H.regenerate_icons() + + playsound(H, 'sound/effects/blobattack.ogg', 30, 1) + var/T = get_turf(src) + new /obj/effect/gibspawner/human(T, H.dna,H.dna.blood_color,H.dna.blood_color) + H.visible_message("With a sickening squish, [src] reforms their whole body, casting their old parts on the floor!", + "We reform our body. We are whole once more.", + "You hear organic matter ripping and tearing!") + ..() + else + to_chat(user,"We were interrupted!") + charge_counter = 9.8 MINUTES + + +//////////////// +//Revive spell// +//////////////// +//Will incapacitate you for 10 minutes, and then you can revive. +/spell/targeted/chimera/hatch + name = "Hatch Stasis" + desc = "We attempt to grow an entirely new body from scratch, or death." + + spell_flags = INCLUDEUSER | GHOSTCAST + hud_state = "ling_regenerative_stasis" + invocation = "none" + invocation_type = SpI_NONE + charge_max = 60 MINUTES + duration = 0 SECONDS + nutrition_cost_minimum = 1 + nutrition_cost_proportional = 1 + + +/spell/targeted/chimera/hatch/cast_check(skipcharge, mob/user = usr) + if(..()) + if(!ishuman(user)) + to_chat(user,"Non-humans can't use this!") + return FALSE + + var/confirmation = alert("You will begin a lengthy process of around ten minutes you cannot cancel- Is this what you want?","Hatching Prompt","Yes", "No") + if(confirmation != "Yes") + to_chat(user, " Hatching cancelled. ") + return FALSE + else return TRUE + +/spell/targeted/chimera/hatch/cast(list/targets, mob/user = usr) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.stat == DEAD) + H.visible_message(" [H] lays eerily still. Something about them seems off, even when dead.","We begin to gather up whatever is left to begin regrowth.") + else + H.visible_message(" [H] suddenly collapses, seizing up and going eerily still. ", "We begin the regrowth process to start anew.") + H.SetParalysis(8000) //admin style self-stun + + //These are only messages to give the player and everyone around them an idea of which stage they're at + //visible_message doesn't seem to relay selfmessages if you're paralysed, so we use to_chat + addtimer(CALLBACK(H, /atom/.proc/visible_message," [H]'s skin begins to ripple and move, as if something was crawling underneath."), 4 MINUTES) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat,H,"We begin to recycle the dead tissue."),4 MINUTES) + + addtimer(CALLBACK(H, /atom/.proc/visible_message," [H]'s body begins to lose its shape, skin sloughing off and melting, losing form and composure.","There is little left. We will soon be ready."), 8 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat,H,"There is little left. We will soon be ready."), 8 MINUTES) + + addtimer(CALLBACK(src, .proc/add_pop,H,), 10 MINUTES) + +/spell/targeted/chimera/hatch/proc/add_pop(mob/user = usr) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.visible_message(" [H] looks ready to burst!") + to_chat(H,"We are ready.") + var/spell/targeted/chimera/hatch_pop/S = new /spell/targeted/chimera/hatch_pop(H) + var/master_type = /obj/screen/movable/spell_master/chimera + H.add_spell(S, "cult", master_type) + + +/////////////////////// +//Actual Revive Spell// +/////////////////////// +//Not to be used normally. Given by the 'hatch' spell +/spell/targeted/chimera/hatch_pop + name = "Emerge" + desc = "We emerge in our new form." + + spell_flags = INCLUDEUSER | GHOSTCAST + hud_state = "ling_revive" + invocation = "none" + invocation_type = SpI_NONE + charge_max = 10 SECONDS //It gets removed after_cast anyway + duration = 0 + nutrition_cost_minimum = 1 + nutrition_cost_proportional = 1 + +/spell/targeted/chimera/hatch_pop/cast(list/targets, mob/user = usr) + var/mob/living/carbon/human/H = user + + var/braindamage = (H.brainloss * 0.6) //Can only heal half brain damage. + + H.revive() + H.mutations.Remove(HUSK) + H.nutrition = 50 //Hungy, also guarantees ferality without any other tweaking + H.setBrainLoss(braindamage) + + //Drop everything + for(var/obj/item/W in H) + H.drop_from_inventory(W) + H.visible_message("[H] emerges from a cloud of viscera!") + H.SetParalysis(0) + //Unfreeze some things + H.does_not_breathe = FALSE + H.update_canmove() + H.weakened = 2 + //Visual effects + var/T = get_turf(H) + new /obj/effect/gibspawner/human(T, H.dna,H.dna.blood_color,H.dna.blood_color) + playsound(T, 'sound/effects/splat.ogg') + +/spell/targeted/chimera/hatch_pop/after_cast(list/targets, mob/user = usr) + var/mob/living/carbon/human/H = user + H.remove_spell(src) + qdel(src) + + +//////////////////// +//Timed No Breathe// +//////////////////// +//Same principle as thermal sight. Could be status effects? +/spell/targeted/chimera/no_breathe + name = "Stop Respiration" + desc = "We change our form to no longer need to breathe at all. We cannot sustain this for long." + + spell_flags = INCLUDEUSER + hud_state = "ling_toggle_breath" + invocation = "none" + invocation_type = SpI_NONE + charge_max = 125 SECONDS //5 seconds inbetween uses + duration = 120 SECONDS + nutrition_cost_minimum = 100 + nutrition_cost_proportional = 20 //Costly. + var/active = FALSE + + +/spell/targeted/chimera/no_breathe/cast(list/targets, mob/user = usr) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + toggle_breath(user) + addtimer(CALLBACK(src, .proc/toggle_breath,H), duration, TIMER_UNIQUE) + ..() + +/spell/targeted/chimera/no_breathe/proc/toggle_breath(mob/living/carbon/human/H) + if(!active) + to_chat(H, "We preserve the air we have, no longer needing to breathe.") + H.does_not_breathe = TRUE + active = TRUE + else + to_chat(H, "Our reserves are drained.") + H.does_not_breathe = FALSE + active = FALSE + + /////////////// //EMP Shriek // /////////////// @@ -125,7 +335,10 @@ var/emp_med = 6 var/emp_light = 9 var/emp_long = 12 - charge_max = 5 MINUTES + smoke_spread = 1 + smoke_amt = 1 + override_base = "cult" + charge_max = 5 MINUTES //Let's not be able to spam this /spell/aoe_turf/dissonant_shriek/before_cast(list/targets, mob/user = usr) @@ -147,17 +360,15 @@ return /spell/aoe_turf/dissonant_shriek/cast(list/targets, mob/user = usr) - for(var/mob/living/T in targets) if(iscarbon(T)) if(T.mind) - if(T.get_ear_protection() >= 2) + if(T.get_ear_protection() >= 2 || T == user) continue to_chat(T, "You hear an extremely loud screeching sound! It slightly \ [pick("confuses","confounds","perturbs","befuddles","dazes","unsettles","disorients")] you.") - if(T != user) - T.Confuse(10) - SEND_SOUND(T, sound('sound/effects/screech.ogg')) + T.Confuse(10) + playsound(get_turf(user),'sound/effects/screech.ogg', 75, TRUE) empulse(get_turf(user), emp_heavy, emp_med, emp_light, emp_long)