From 80c954c6a033afed4fa867015b4f0122eb3dc49b Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Sat, 1 Jul 2023 21:44:19 -0500 Subject: [PATCH] Adds a new passive changeling ability - the Defibrillator Grasp. Adds support for 0 cost changeling abilities. (#76301) ## About The Pull Request ![image](https://github.com/tgstation/tgstation/assets/51863163/190d0dda-6899-468d-9a3e-5df05d7b1414) - Adds a new PASSIVE changeling ability, totally not stolen from The Thing, called Defibrillator Grasp. If someone attempts to defibrillate your body while you are in stasis or dead, you will instantly be revived at full strength. Additionally, the person doing the defibbing will have both of their arms removed (or if they're a cyborg they'll just be stunned). - Adds support for 0 cost changeling abilities. DNA sting is now 0 cost / optionally learned. ## Why It's Good For The Game The intent of this ability to add a new avenue for stealthier changelings to spring upon their victims - faking their death only to get brought to medical, then springing up like a bat out of hell and pouncing upon a now vulnerable medical doctor. Or maybe pretending to be another type of criminal to get brought to the brig medbay and revived, then suddenly jumping up and striking out. As for the DNA sting change - Ling gets a ton of buttons to start and people don't often use a lot of them. DNA sting is a prime example. By moving some to just "zero cost, optional", trims down on some action ability bloat. ## Changelog :cl: Melbert add: Added a new 0 cost passive changeling ability, the Defibrillator Grasp. add: DNA sing is now no longer innate, but 0 cost, allowing changelings to not take it if they don't plan on using it. /:cl: --- code/__DEFINES/antagonists.dm | 8 ++ code/__DEFINES/changeling.dm | 4 - code/__DEFINES/dcs/signals/signals_medical.dm | 7 +- code/game/objects/items/defib.dm | 3 + .../changeling/cellular_emporium.dm | 4 +- .../antagonists/changeling/changeling.dm | 4 +- .../changeling/changeling_power.dm | 36 ++++++-- .../antagonists/changeling/powers/absorb.dm | 2 +- .../changeling/powers/defib_grasp.dm | 92 +++++++++++++++++++ .../changeling/powers/fakedeath.dm | 69 +++++++++++--- .../changeling/powers/mutations.dm | 4 +- .../changeling/powers/regenerate.dm | 2 +- .../changeling/powers/transform.dm | 2 +- .../antagonists/revolution/revolution.dm | 2 - code/modules/mob/living/init_signals.dm | 14 ++- code/modules/mob/living/status_procs.dm | 1 - tgstation.dme | 2 +- .../tgui/interfaces/AntagInfoChangeling.tsx | 2 +- 18 files changed, 215 insertions(+), 43 deletions(-) delete mode 100644 code/__DEFINES/changeling.dm create mode 100644 code/modules/antagonists/changeling/powers/defib_grasp.dm diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 90d61e403dd..1f8a99d9d8c 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -338,6 +338,14 @@ GLOBAL_LIST_INIT(human_invader_antagonists, list( #define HUNTER_PACK_BOUNTY "Bounty Fugitive Hunters" #define HUNTER_PACK_PSYKER "Psyker Fugitive Hunters" +/// Changeling abilities with DNA cost = this are innately given to all changelings +#define CHANGELING_POWER_INNATE -1 +/// Changeling abilities with DNA cost = this are not obtainable by changelings - either used for secret unlockable or abstract abilities +#define CHANGELING_POWER_UNOBTAINABLE -2 + +/// For changelings, this is how many recent say lines are retained when absorbing a mob +#define LING_ABSORB_RECENT_SPEECH 8 + // Various abductor equipment modes. #define VEST_STEALTH 1 diff --git a/code/__DEFINES/changeling.dm b/code/__DEFINES/changeling.dm deleted file mode 100644 index 1913e62c0e9..00000000000 --- a/code/__DEFINES/changeling.dm +++ /dev/null @@ -1,4 +0,0 @@ -/// The duration of the fakedeath coma. -#define LING_FAKEDEATH_TIME (40 SECONDS) -/// The number of recent spoken lines to gain on absorbing a mob -#define LING_ABSORB_RECENT_SPEECH 8 diff --git a/code/__DEFINES/dcs/signals/signals_medical.dm b/code/__DEFINES/dcs/signals/signals_medical.dm index 801eb6b41bb..2dca6487f70 100644 --- a/code/__DEFINES/dcs/signals/signals_medical.dm +++ b/code/__DEFINES/dcs/signals/signals_medical.dm @@ -4,9 +4,14 @@ /// From /datum/surgery_step/success(): (datum/surgery_step/step, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results) #define COMSIG_MOB_SURGERY_STEP_SUCCESS "mob_surgery_step_success" +/// From /obj/item/shockpaddles/do_help, after the defib do_after is complete, but before any effects are applied: (mob/living/defibber, obj/item/shockpaddles/source) +#define COMSIG_DEFIBRILLATOR_PRE_HELP_ZAP "carbon_being_defibbed" + /// Return to stop default defib handling + #define COMPONENT_DEFIB_STOP (1<<0) + /// From /obj/item/shockpaddles/proc/do_success(): (obj/item/shockpaddles/source) #define COMSIG_DEFIBRILLATOR_SUCCESS "defib_success" - #define COMPONENT_DEFIB_STOP (1<<0) + // #define COMPONENT_DEFIB_STOP (1<<0) // Same return, to stop default defib handling /// From /datum/surgery/can_start(): (mob/source, datum/surgery/surgery, mob/living/patient) #define COMSIG_SURGERY_STARTING "surgery_starting" diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 1d370c4fbbb..aa2f59f4c7d 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -592,6 +592,9 @@ playsound(src, 'sound/machines/defib_failed.ogg', 50, FALSE) do_cancel() return + if(SEND_SIGNAL(H, COMSIG_DEFIBRILLATOR_PRE_HELP_ZAP, user, src) & COMPONENT_DEFIB_STOP) + do_cancel() + return if(H.stat == DEAD) H.visible_message(span_warning("[H]'s body convulses a bit.")) playsound(src, SFX_BODYFALL, 50, TRUE) diff --git a/code/modules/antagonists/changeling/cellular_emporium.dm b/code/modules/antagonists/changeling/cellular_emporium.dm index b4f3ebd2049..d3f7c8d1f8d 100644 --- a/code/modules/antagonists/changeling/cellular_emporium.dm +++ b/code/modules/antagonists/changeling/cellular_emporium.dm @@ -41,7 +41,7 @@ var/dna_cost = initial(ability_path.dna_cost) - if(dna_cost <= 0) + if(dna_cost < 0) continue var/list/ability_data = list() @@ -57,7 +57,7 @@ can_purchase = FALSE if(initial(ability_path.req_dna) > changeling.absorbed_count) can_purchase = FALSE - if(dna_cost > genetic_points_remaining) + if(dna_cost > 0 && dna_cost > genetic_points_remaining) can_purchase = FALSE ability_data["can_purchase"] = can_purchase diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 355f33f6410..8fc6f3d6c16 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -229,11 +229,11 @@ /* * Instantiate all the default actions of a ling (transform, dna sting, absorb, etc) - * Any Changeling action with `dna_cost == 0` will be added here automatically + * Any Changeling action with dna_cost = CHANGELING_POWER_INNATE will be added here automatically */ /datum/antagonist/changeling/proc/create_innate_actions() for(var/datum/action/changeling/path as anything in all_powers) - if(initial(path.dna_cost) != 0) + if(initial(path.dna_cost) != CHANGELING_POWER_INNATE) continue var/datum/action/changeling/innate_ability = new path() diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm index 96cad510735..1c070a2315a 100644 --- a/code/modules/antagonists/changeling/changeling_power.dm +++ b/code/modules/antagonists/changeling/changeling_power.dm @@ -7,17 +7,33 @@ background_icon_state = "bg_changeling" overlay_icon_state = "bg_changeling_border" button_icon = 'icons/mob/actions/actions_changeling.dmi' - var/needs_button = TRUE//for passive abilities like hivemind that dont need a button - var/helptext = "" // Details - var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands) - var/dna_cost = -1 //cost of the sting in dna points. 0 = auto-purchase (see changeling.dm), -1 = cannot be purchased - var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1 - var/req_human = FALSE //if you need to be human to use this ability - var/req_absorbs = 0 //similar to req_dna, but only gained from absorbing, not DNA sting - ///Maximum stat before the ability is blocked. For example, `UNCONSCIOUS` prevents it from being used when in hard crit or dead, while `DEAD` allows the ability to be used on any stat values. + /// For passive abilities like hivemind that dont need an action button + var/needs_button = TRUE + /// Details displayed in fine print within the changling emporium + var/helptext = "" + /// How many changeling chems it costs to use + var/chemical_cost = 0 + /** + * Cost of the ability in dna points, negative values are not valid + * + * Special numbers include [CHANGELING_POWER_INNATE], which are given to changeling for free without bring prompted + * and [CHANGELING_POWER_UNOBTAINABLE], which are not available for purchase in the changeling emporium + */ + var/dna_cost = CHANGELING_POWER_UNOBTAINABLE + /// Amount of dna needed to use this ability. Note, changelings always have atleast 1 + var/req_dna = 0 + /// If you need to be humanoid to use this ability (disincludes monkeys) + var/req_human = FALSE + /// Similar to req_dna, but only gained from absorbing, not DNA sting + var/req_absorbs = 0 + /// Maximum stat before the ability is blocked. + /// For example, `UNCONSCIOUS` prevents it from being used when in hard crit or dead, + /// while `DEAD` allows the ability to be used on any stat values. var/req_stat = CONSCIOUS - var/ignores_fakedeath = FALSE // usable with the FAKEDEATH flag - var/active = FALSE//used by a few powers that toggle + /// usable when the changeling is in death coma + var/ignores_fakedeath = FALSE + /// used by a few powers that toggle + var/active = FALSE /* changeling code now relies on on_purchase to grant powers. diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index 9a295fc8ac2..c2ae89933d1 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -3,7 +3,7 @@ desc = "Absorb the DNA of our victim. Requires us to strangle them." button_icon_state = "absorb_dna" chemical_cost = 0 - dna_cost = 0 + dna_cost = CHANGELING_POWER_INNATE req_human = TRUE ///if we're currently absorbing, used for sanity var/is_absorbing = FALSE diff --git a/code/modules/antagonists/changeling/powers/defib_grasp.dm b/code/modules/antagonists/changeling/powers/defib_grasp.dm new file mode 100644 index 00000000000..c99774df536 --- /dev/null +++ b/code/modules/antagonists/changeling/powers/defib_grasp.dm @@ -0,0 +1,92 @@ +/datum/action/changeling/defib_grasp + name = "Defibrillator Grasp" + desc = "We prepare ourselves while in stasis. If one of our enemies attempts to defibrillate us, \ + we will snatch their arms off and instantly finalize our stasis." + helptext = "This ability is passive, and will trigger when a defibrillator paddle is applied to our chest \ + while we are dead or in stasis. Will also stun cyborgs momentarily." + needs_button = FALSE + dna_cost = 0 + + /// Flags to pass to fully heal when we get zapped + var/heal_flags = HEAL_DAMAGE|HEAL_BODY|HEAL_STATUS|HEAL_CC_STATUS + +/datum/action/changeling/defib_grasp/on_purchase(mob/user, is_respec) + . = ..() + RegisterSignal(user, COMSIG_DEFIBRILLATOR_PRE_HELP_ZAP, PROC_REF(on_defibbed)) + +/// Signal proc for [COMSIG_DEFIBRILLATOR_PRE_HELP_ZAP]. +/datum/action/changeling/defib_grasp/proc/on_defibbed(mob/living/carbon/source, mob/living/defibber, obj/item/shockpaddles/defib) + SIGNAL_HANDLER + + if(source.stat != DEAD && !HAS_TRAIT_FROM(source, TRAIT_FAKEDEATH, CHANGELING_TRAIT)) + return + + INVOKE_ASYNC(src, PROC_REF(execute_defib), source, defibber, defib) + return COMPONENT_DEFIB_STOP + +/// Executes the defib action, causing the changeling to fully heal and get up. +/datum/action/changeling/defib_grasp/proc/execute_defib(mob/living/carbon/changeling, mob/living/defibber, obj/item/shockpaddles/defib) + remove_arms(changeling, defibber, defib) + + if(changeling.stat == DEAD) + changeling.revive(heal_flags) + else + changeling.fully_heal(heal_flags) + + changeling.cure_fakedeath(CHANGELING_TRAIT) // rips us out of revival stasis (if we're in it) + changeling.buckled?.unbuckle_mob(changeling) // get us off of stasis beds please + changeling.set_resting(FALSE) + changeling.adjust_jitter(20 SECONDS) + changeling.emote("scream") + playsound(changeling, 'sound/magic/demon_consume.ogg', 50, TRUE) + + // Mimics some real defib stuff (wish this was more generalized) + playsound(defib, SFX_BODYFALL, 50, TRUE) + playsound(defib, 'sound/machines/defib_zap.ogg', 75, TRUE, -1) + playsound(defib, 'sound/machines/defib_success.ogg', 50, FALSE) // I guess + defib.shock_pulling(30, changeling) + +/// Removes the arms of the defibber if they're a carbon, and stuns them for a bit. +/// If they're a cyborg, they'll just get stunned instead. +/datum/action/changeling/defib_grasp/proc/remove_arms(mob/living/carbon/changeling, mob/living/defibber, obj/item/shockpaddles/defib) + + if(iscyborg(defibber)) + if(defibber.flash_act(affect_silicon = TRUE)) + to_chat(defibber, span_userdanger("[changeling] awakens suddenly, overloading your sensors!")) + // run default visible message regardless, no overt indication of the cyborg being overloaded to watchers + + else + defibber.Stun(4 SECONDS) // stuck defibbing + + if(iscarbon(defibber)) + var/removed_arms = 0 + var/mob/living/carbon/carbon_defibber = defibber + for(var/obj/item/bodypart/arm/limb in carbon_defibber.bodyparts) + if(limb.dismember(silent = FALSE)) + removed_arms++ + qdel(limb) + + if(removed_arms) + // OH GOOD HEAVENS + defibber.adjust_jitter(3 MINUTES) + defibber.adjust_dizzy(1 MINUTES) + defibber.adjust_stutter(1 MINUTES) + defibber.adjust_eye_blur(10 SECONDS) + defibber.emote("scream") + + changeling.visible_message( + span_bolddanger("[changeling] awakens suddenly, snatching [defib] out of [defibber]'s hands while ripping off [removed_arms >= 2 ? "" : "one of "][defibber.p_their()] arms!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ignored_mobs = list(changeling, defibber), + ) + to_chat(changeling, span_changeling("The power of [defib] course through us, reviving us from our stasis! \ + With this newfound energy, we snap [removed_arms >= 2 ? "" : "one of "][defibber]'s arms off!")) + to_chat(defibber, span_userdanger("[changeling] awakens suddenly, snapping [removed_arms >= 2 ? "" : "one of "]your arms off!")) + return // no default message if we got an arm + + changeling.visible_message( + span_bolddanger("[changeling] awakens suddenly!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ignored_mobs = changeling, + ) + to_chat(changeling, span_changeling("The power of [defib] course through us, reviving us from our stasis!")) diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm index 40a71f6ce84..c6fa466cdb1 100644 --- a/code/modules/antagonists/changeling/powers/fakedeath.dm +++ b/code/modules/antagonists/changeling/powers/fakedeath.dm @@ -3,10 +3,15 @@ desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals." button_icon_state = "fake_death" chemical_cost = 15 - dna_cost = 0 + dna_cost = CHANGELING_POWER_INNATE req_dna = 1 req_stat = DEAD ignores_fakedeath = TRUE + + /// How long it takes for revival to ready upon entering stasis. + /// The changelin can opt to stay in fakedeath for longer, though. + var/fakedeath_duration = 40 SECONDS + /// If TRUE, we're ready to revive and can click the button to heal. var/revive_ready = FALSE //Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. @@ -14,25 +19,63 @@ ..() if(revive_ready) INVOKE_ASYNC(src, PROC_REF(revive), user) - revive_ready = FALSE - chemical_cost = 15 - to_chat(user, span_notice("We have revived ourselves.")) - build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) + disable_revive(user) // this should be already called via signal, but just incase something wacky happens + else to_chat(user, span_notice("We begin our stasis, preparing energy to arise once more.")) - user.fakedeath(CHANGELING_TRAIT) //play dead - addtimer(CALLBACK(src, PROC_REF(ready_to_regenerate), user), LING_FAKEDEATH_TIME, TIMER_UNIQUE) + enable_fakedeath(user) + return TRUE +/// Used to enable fakedeath and register relevant signals / start timers +/datum/action/changeling/fakedeath/proc/enable_fakedeath(mob/living/changeling) + if(revive_ready || HAS_TRAIT_FROM(changeling, TRAIT_DEATHCOMA, CHANGELING_TRAIT)) + return + + changeling.fakedeath(CHANGELING_TRAIT) + addtimer(CALLBACK(src, PROC_REF(ready_to_regenerate), changeling), fakedeath_duration, TIMER_UNIQUE) + RegisterSignal(changeling, SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA), PROC_REF(fakedeath_reset)) + +/// Sets [revive_ready] to FALSE and updates the button icons. +/datum/action/changeling/fakedeath/proc/disable_revive(mob/living/changeling) + if(!revive_ready) + return + + chemical_cost = 15 + revive_ready = FALSE + build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) + UnregisterSignal(changeling, SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA)) + +/// Sets [revive_ready] to TRUE and updates the button icons. +/datum/action/changeling/fakedeath/proc/enable_revive(mob/living/changeling) + if(revive_ready) + return + + chemical_cost = 0 + revive_ready = TRUE + build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) + +/// Signal proc to stop the revival process if the changeling exits their stasis early. +/datum/action/changeling/fakedeath/proc/fakedeath_reset(datum/source) + SIGNAL_HANDLER + + if(HAS_TRAIT_FROM(source, TRAIT_DEATHCOMA, CHANGELING_TRAIT)) + return + + disable_revive(source) + /datum/action/changeling/fakedeath/proc/revive(mob/living/carbon/user) if(!istype(user)) return + if(!HAS_TRAIT_FROM(user, TRAIT_DEATHCOMA, CHANGELING_TRAIT)) + return user.cure_fakedeath(CHANGELING_TRAIT) // Heal all damage and some minor afflictions, var/flags_to_heal = (HEAL_DAMAGE|HEAL_BODY|HEAL_STATUS|HEAL_CC_STATUS) // but leave out limbs so we can do it specially user.revive(flags_to_heal & ~HEAL_LIMBS) + to_chat(user, span_notice("We have revived ourselves.")) var/static/list/dont_regenerate = list(BODY_ZONE_HEAD) // headless changelings are funny if(!length(user.get_missing_limbs() - dont_regenerate)) @@ -49,17 +92,17 @@ user.regenerate_limbs(dont_regenerate) /datum/action/changeling/fakedeath/proc/ready_to_regenerate(mob/user) - if(!user?.mind) + if(QDELETED(src) || QDELETED(user)) return - var/datum/antagonist/changeling/ling = user.mind.has_antag_datum(/datum/antagonist/changeling) - if(!ling || !(src in ling.innate_powers)) + var/datum/antagonist/changeling/ling = user.mind?.has_antag_datum(/datum/antagonist/changeling) + if(QDELETED(ling) || !(src in ling.innate_powers + ling.purchased_powers)) // checking both innate and purchased for full coverage + return + if(!HAS_TRAIT_FROM(user, TRAIT_DEATHCOMA, CHANGELING_TRAIT)) return to_chat(user, span_notice("We are ready to revive.")) - chemical_cost = 0 - revive_ready = TRUE - build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) + enable_revive(user) /datum/action/changeling/fakedeath/can_sting(mob/living/user) if(revive_ready) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index fbbd4185e7e..6578051794f 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -15,7 +15,7 @@ desc = "Go tell a coder if you see this" helptext = "Yell at Miauw and/or Perakp" chemical_cost = 1000 - dna_cost = -1 + dna_cost = CHANGELING_POWER_UNOBTAINABLE var/silent = FALSE var/weapon_type @@ -88,7 +88,7 @@ desc = "Go tell a coder if you see this" helptext = "Yell at Miauw and/or Perakp" chemical_cost = 1000 - dna_cost = -1 + dna_cost = CHANGELING_POWER_UNOBTAINABLE var/helmet_type = /obj/item var/suit_type = /obj/item diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm index 3716a0b40cb..6595e331195 100644 --- a/code/modules/antagonists/changeling/powers/regenerate.dm +++ b/code/modules/antagonists/changeling/powers/regenerate.dm @@ -4,7 +4,7 @@ helptext = "Will alert nearby crew if any external limbs are regenerated. Can be used while unconscious." button_icon_state = "regenerate" chemical_cost = 10 - dna_cost = 0 + dna_cost = CHANGELING_POWER_INNATE req_stat = HARD_CRIT /datum/action/changeling/regenerate/sting_action(mob/living/user) diff --git a/code/modules/antagonists/changeling/powers/transform.dm b/code/modules/antagonists/changeling/powers/transform.dm index 256dfe62ecc..804dd2bffac 100644 --- a/code/modules/antagonists/changeling/powers/transform.dm +++ b/code/modules/antagonists/changeling/powers/transform.dm @@ -3,7 +3,7 @@ desc = "We take on the appearance and voice of one we have absorbed. Costs 5 chemicals." button_icon_state = "transform" chemical_cost = 5 - dna_cost = 0 + dna_cost = CHANGELING_POWER_INNATE req_dna = 1 req_human = TRUE diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index 85a79769f3f..63a11ecef7c 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -559,7 +559,6 @@ if(player_mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) ADD_TRAIT(player, TRAIT_DEFIB_BLACKLISTED, REF(src)) - player.med_hud_set_status() for(var/datum/job/job as anything in SSjob.joinable_occupations) if(!(job.departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY|DEPARTMENT_BITFLAG_COMMAND))) @@ -626,7 +625,6 @@ for (var/datum/mind/rev_head as anything in ex_headrevs) if(!isnull(rev_head.current)) ADD_TRAIT(rev_head.current, TRAIT_DEFIB_BLACKLISTED, REF(src)) - rev_head.current.med_hud_set_status() for(var/datum/objective/mutiny/head_tracker in objectives) var/mob/living/head_of_staff = head_tracker.target?.current diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index 6c4d59f93df..aeb29714218 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -6,6 +6,14 @@ RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_DEATHCOMA), PROC_REF(on_deathcoma_trait_gain)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_DEATHCOMA), PROC_REF(on_deathcoma_trait_loss)) + RegisterSignals(src, list( + SIGNAL_ADDTRAIT(TRAIT_FAKEDEATH), + SIGNAL_REMOVETRAIT(TRAIT_FAKEDEATH), + + SIGNAL_ADDTRAIT(TRAIT_DEFIB_BLACKLISTED), + SIGNAL_REMOVETRAIT(TRAIT_DEFIB_BLACKLISTED), + ), PROC_REF(update_medhud_on_signal)) + RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_IMMOBILIZED), PROC_REF(on_immobilized_trait_gain)) RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_IMMOBILIZED), PROC_REF(on_immobilized_trait_loss)) @@ -66,7 +74,6 @@ if(stat <= UNCONSCIOUS) update_stat() - /// Called when [TRAIT_DEATHCOMA] is added to the mob. /mob/living/proc/on_deathcoma_trait_gain(datum/source) SIGNAL_HANDLER @@ -77,6 +84,11 @@ SIGNAL_HANDLER REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, TRAIT_DEATHCOMA) +/// Updates medhud when recieving relevant signals. +/mob/living/proc/update_medhud_on_signal(datum/source) + SIGNAL_HANDLER + med_hud_set_health() + med_hud_set_status() /// Called when [TRAIT_IMMOBILIZED] is added to the mob. /mob/living/proc/on_immobilized_trait_gain(datum/source) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index accbf9de890..16f0d3d2daa 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -524,7 +524,6 @@ add_traits(list(TRAIT_FAKEDEATH, TRAIT_DEATHCOMA), source) tod = station_time_timestamp() - ///Unignores all slowdowns that lack the IGNORE_NOSLOW flag. /mob/living/proc/unignore_slowdown(source) REMOVE_TRAIT(src, TRAIT_IGNORESLOWDOWN, source) diff --git a/tgstation.dme b/tgstation.dme index 7fd54ca73ef..bb0c7abebb1 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -60,7 +60,6 @@ #include "code\__DEFINES\callbacks.dm" #include "code\__DEFINES\cameranets.dm" #include "code\__DEFINES\cargo.dm" -#include "code\__DEFINES\changeling.dm" #include "code\__DEFINES\chat.dm" #include "code\__DEFINES\chat_filter.dm" #include "code\__DEFINES\cleaning.dm" @@ -2557,6 +2556,7 @@ #include "code\modules\antagonists\changeling\powers\augmented_eyesight.dm" #include "code\modules\antagonists\changeling\powers\biodegrade.dm" #include "code\modules\antagonists\changeling\powers\chameleon_skin.dm" +#include "code\modules\antagonists\changeling\powers\defib_grasp.dm" #include "code\modules\antagonists\changeling\powers\digitalcamo.dm" #include "code\modules\antagonists\changeling\powers\fakedeath.dm" #include "code\modules\antagonists\changeling\powers\fleshmend.dm" diff --git a/tgui/packages/tgui/interfaces/AntagInfoChangeling.tsx b/tgui/packages/tgui/interfaces/AntagInfoChangeling.tsx index 497942fe142..88eb71cd5a5 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoChangeling.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoChangeling.tsx @@ -167,7 +167,7 @@ const AbilitiesSection = (props, context) => { Your  Absorb DNA ability allows - you to steal the DNA and memories of a victim. Your + you to steal the DNA and memories of a victim. The  Extract DNA Sting ability also steals the DNA of a victim, and is undetectable, but does not grant you their memories or speech patterns.