From 33da2f07ea283128e9bc3cd900debc59056a7dcb Mon Sep 17 00:00:00 2001 From: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Date: Mon, 16 Jun 2025 03:04:59 +0200 Subject: [PATCH] Adds a bunch of owner.current nullchecks to antag code (#91524) This could cause runtimes preventing antag datum removal in case your body got destroyed. Ideally we'd unit test for this, but I can't get it to work sanely without touching some dynamic code (due to some antag datums requiring a bunch of snowflaky setups), so the unit test will come after its refactored. :cl: fix: Fixed some edge cases where antagonist datums would "stick" and not get removed if your body got destroyed. /:cl: --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- code/datums/mind/antag.dm | 6 ++++-- code/modules/antagonists/_common/antag_datum.dm | 10 ++++++---- code/modules/antagonists/ashwalker/ashwalker.dm | 2 ++ .../antagonists/changeling/changeling.dm | 3 ++- code/modules/antagonists/clown_ops/clownop.dm | 2 -- code/modules/antagonists/cult/datums/cultist.dm | 5 ++++- .../antagonists/fugitive/hunters/hunter.dm | 5 ++--- .../antagonists/heretic/heretic_antag.dm | 9 +++++---- code/modules/antagonists/malf_ai/malf_ai.dm | 7 +++---- code/modules/antagonists/nightmare/nightmare.dm | 2 +- code/modules/antagonists/pirate/pirate.dm | 4 ++-- .../antagonists/pyro_slime/pyro_slime.dm | 2 +- .../antagonists/revolution/revolution.dm | 17 +++++++++++------ code/modules/antagonists/spiders/spiders.dm | 2 +- .../syndicate_monkey/syndicate_monkey.dm | 2 +- .../antagonists/traitor/datum_traitor.dm | 1 - .../venus_human_trap/venus_human_trap.dm | 2 +- .../antagonists/voidwalker/voidwalker.dm | 2 +- code/modules/antagonists/xeno/xeno.dm | 2 +- 19 files changed, 48 insertions(+), 37 deletions(-) diff --git a/code/datums/mind/antag.dm b/code/datums/mind/antag.dm index 169bd7ef92a..7f65cb8fdc7 100644 --- a/code/datums/mind/antag.dm +++ b/code/datums/mind/antag.dm @@ -34,14 +34,14 @@ var/datum/antagonist/A = has_antag_datum(datum_type) if(A) A.on_removal() - current.log_message("has lost antag datum [A.name]([A.type]).", LOG_GAME) + current?.log_message("has lost antag datum [A.name]([A.type]).", LOG_GAME) return TRUE /datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us. for(var/a in antag_datums) var/datum/antagonist/A = a A.on_removal() - current.log_message("has lost all antag datums.", LOG_GAME) + current?.log_message("has lost all antag datums.", LOG_GAME) /datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE) if(!datum_type) @@ -93,6 +93,8 @@ /datum/mind/proc/remove_antag_equip() + if(!current) + return var/list/Mob_Contents = current.get_contents() for(var/obj/item/I in Mob_Contents) var/datum/component/uplink/O = I.GetComponent(/datum/component/uplink) //Todo make this reset signal diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index e7e3b8476f5..7f93e0c57ce 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -194,7 +194,8 @@ GLOBAL_LIST_EMPTY(antagonists) ///Called by the transfer_to() mind proc after the mind (mind.current and new_character.mind) has moved but before the player (key and client) is transferred. /datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body) SHOULD_CALL_PARENT(TRUE) - remove_innate_effects(old_body) + if(old_body) + remove_innate_effects(old_body) if(old_body && old_body.stat != DEAD && !LAZYLEN(old_body.mind?.antag_datums)) old_body.remove_from_current_living_antags() var/datum/action/antag_info/info_button = info_button_ref?.resolve() @@ -318,10 +319,11 @@ GLOBAL_LIST_EMPTY(antagonists) if(!owner) CRASH("Antag datum with no owner.") - remove_innate_effects() + if(owner.current) + remove_innate_effects() clear_antag_moodies() LAZYREMOVE(owner.antag_datums, src) - if(!LAZYLEN(owner.antag_datums)) + if(!LAZYLEN(owner.antag_datums) && owner.current) owner.current.remove_from_current_living_antags() if(info_button_ref) QDEL_NULL(info_button_ref) @@ -362,7 +364,7 @@ GLOBAL_LIST_EMPTY(antagonists) * Use this proc for playing sounds, sending alerts, or otherwise informing the player that they're no longer a specific antagonist type. */ /datum/antagonist/proc/farewell() - if(!silent) + if(!silent && owner.current) to_chat(owner.current, span_userdanger("You are no longer \the [src]!")) /** diff --git a/code/modules/antagonists/ashwalker/ashwalker.dm b/code/modules/antagonists/ashwalker/ashwalker.dm index 5b42239cf7e..015677de5af 100644 --- a/code/modules/antagonists/ashwalker/ashwalker.dm +++ b/code/modules/antagonists/ashwalker/ashwalker.dm @@ -34,6 +34,8 @@ /datum/antagonist/ashwalker/on_removal() . = ..() + if(!owner.current) + return UnregisterSignal(owner.current, COMSIG_MOB_EXAMINATE) if(!(FACTION_NEUTRAL in owner.current.faction)) owner.current.faction.Add(FACTION_NEUTRAL) diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 7c0e5261d33..288e935bc35 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -242,7 +242,8 @@ return ..() /datum/antagonist/changeling/farewell() - to_chat(owner.current, span_userdanger("You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!")) + if(owner.current) + to_chat(owner.current, span_userdanger("You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!")) /* * Instantiate the cellular emporium for the changeling. diff --git a/code/modules/antagonists/clown_ops/clownop.dm b/code/modules/antagonists/clown_ops/clownop.dm index 9e2b79102b1..e1e9b313f45 100644 --- a/code/modules/antagonists/clown_ops/clownop.dm +++ b/code/modules/antagonists/clown_ops/clownop.dm @@ -24,7 +24,6 @@ /datum/antagonist/nukeop/clownop/remove_innate_effects(mob/living/mob_override) var/mob/living/L = owner.current || mob_override REMOVE_TRAIT(L.mind, TRAIT_NAIVE, CLOWNOP_TRAIT) - return ..() /datum/antagonist/nukeop/clownop/equip_op() . = ..() @@ -56,7 +55,6 @@ /datum/antagonist/nukeop/leader/clownop/remove_innate_effects(mob/living/mob_override) var/mob/living/L = owner.current || mob_override REMOVE_TRAIT(L.mind, TRAIT_NAIVE, CLOWNOP_TRAIT) - return ..() /datum/antagonist/nukeop/leader/clownop/equip_op() . = ..() diff --git a/code/modules/antagonists/cult/datums/cultist.dm b/code/modules/antagonists/cult/datums/cultist.dm index b6c4b947e34..234949084dc 100644 --- a/code/modules/antagonists/cult/datums/cultist.dm +++ b/code/modules/antagonists/cult/datums/cultist.dm @@ -39,6 +39,9 @@ current.log_message("has been converted to the cult of Nar'Sie!", LOG_ATTACK, color=COLOR_CULT_RED) /datum/antagonist/cult/on_removal() + if (!owner.current) + return ..() + if(!silent) owner.current.visible_message(span_deconversion_message("[owner.current] looks like [owner.current.p_theyve()] just reverted to [owner.current.p_their()] old faith!"), ignored_mobs = owner.current) to_chat(owner.current, span_userdanger("An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.")) @@ -238,7 +241,7 @@ /datum/antagonist/cult/proc/deathrattle(datum/source) SIGNAL_HANDLER - if(owner.current.stat != DEAD) + if(owner.current?.stat != DEAD) return if(!QDELETED(GLOB.cult_narsie)) return diff --git a/code/modules/antagonists/fugitive/hunters/hunter.dm b/code/modules/antagonists/fugitive/hunters/hunter.dm index 5d8389a335c..d65cdc75949 100644 --- a/code/modules/antagonists/fugitive/hunters/hunter.dm +++ b/code/modules/antagonists/fugitive/hunters/hunter.dm @@ -80,10 +80,9 @@ /datum/antagonist/fugitive_hunter/remove_innate_effects(mob/living/mob_override) var/mob/living/owner_mob = mob_override || owner.current - //bubber edit; spinwarder removed + // BUBBER EDIT CHANGE BEGIN: spinwarder removed owner_mob.remove_language(/datum/language/panslavic, source = LANGUAGE_BOUNTYHUNTER) - //edit end - return ..() + // BUBBER EDIT CHANGE END /datum/team/fugitive_hunters var/backstory = "error" diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index 1994acd7057..69ed76df700 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -259,7 +259,7 @@ return finish_preview_icon(icon) /datum/antagonist/heretic/farewell() - if(!silent) + if(!silent && owner.current) to_chat(owner.current, span_userdanger("Your mind begins to flare as the otherwordly knowledge escapes your grasp!")) return ..() @@ -278,9 +278,10 @@ return ..() /datum/antagonist/heretic/on_removal() - for(var/knowledge_index in researched_knowledge) - var/datum/heretic_knowledge/knowledge = researched_knowledge[knowledge_index] - knowledge.on_lose(owner.current, src) + if(owner.current) + for(var/knowledge_index in researched_knowledge) + var/datum/heretic_knowledge/knowledge = researched_knowledge[knowledge_index] + knowledge.on_lose(owner.current, src) QDEL_LIST_ASSOC_VAL(researched_knowledge) return ..() diff --git a/code/modules/antagonists/malf_ai/malf_ai.dm b/code/modules/antagonists/malf_ai/malf_ai.dm index 3c4e0296f91..4f78ceef99b 100644 --- a/code/modules/antagonists/malf_ai/malf_ai.dm +++ b/code/modules/antagonists/malf_ai/malf_ai.dm @@ -138,8 +138,6 @@ datum_owner.AddComponent(/datum/component/codeword_hearing, GLOB.syndicate_code_response_regex, "red", src) /datum/antagonist/malf_ai/remove_innate_effects(mob/living/mob_override) - . = ..() - var/mob/living/silicon/ai/datum_owner = mob_override || owner.current if(istype(datum_owner)) @@ -270,7 +268,8 @@ result += span_greentext("The [special_role_text] was successful!") else result += span_redtext("The [special_role_text] has failed!") - SEND_SOUND(owner.current, 'sound/ambience/misc/ambifailure.ogg') + if(owner.current) + SEND_SOUND(owner.current, 'sound/ambience/misc/ambifailure.ogg') return result.Join("
") @@ -288,7 +287,7 @@ SIGNAL_HANDLER var/mob/living/silicon/ai/malf_owner = owner.current - if(malf_owner.linked_core) + if(malf_owner?.linked_core) return COMPONENT_CORE_ALL_GOOD return COMPONENT_CORE_DISCONNECTED diff --git a/code/modules/antagonists/nightmare/nightmare.dm b/code/modules/antagonists/nightmare/nightmare.dm index f5e795fa3d6..256833482c9 100644 --- a/code/modules/antagonists/nightmare/nightmare.dm +++ b/code/modules/antagonists/nightmare/nightmare.dm @@ -39,7 +39,7 @@ ..() /datum/objective/nightmare_fluff/check_completion() - return owner.current.stat != DEAD + return owner.current && owner.current.stat != DEAD /datum/antagonist/nightmare/forge_objectives() var/datum/objective/nightmare_fluff/objective = new diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm index 6bff6eb3572..4b0d3199fbb 100644 --- a/code/modules/antagonists/pirate/pirate.dm +++ b/code/modules/antagonists/pirate/pirate.dm @@ -48,8 +48,8 @@ /datum/antagonist/pirate/remove_innate_effects(mob/living/mob_override) var/mob/living/owner_mob = mob_override || owner.current - owner_mob.remove_language(/datum/language/piratespeak, source = LANGUAGE_PIRATE) - return ..() + if (owner_mob) + owner_mob.remove_language(/datum/language/piratespeak, source = LANGUAGE_PIRATE) /datum/team/pirate name = "\improper Pirate crew" diff --git a/code/modules/antagonists/pyro_slime/pyro_slime.dm b/code/modules/antagonists/pyro_slime/pyro_slime.dm index 7c4f1ef39af..49b4c8b3286 100644 --- a/code/modules/antagonists/pyro_slime/pyro_slime.dm +++ b/code/modules/antagonists/pyro_slime/pyro_slime.dm @@ -18,7 +18,7 @@ explanation_text = "I am fire. I am hunger. The cold is agony. The living pulse with energy; their warmth fuels me. The dead are husks, their embers long faded. Water is death. Fire... fire is freedom." /datum/objective/pyro_slime/check_completion() - return owner.current.stat != DEAD + return owner.current && owner.current.stat != DEAD /datum/antagonist/pyro_slime/forge_objectives() var/datum/objective/pyro_slime/objective = new diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index c8c3ab96115..c3269dc4ca3 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -184,11 +184,14 @@ return COMPONENT_MINDSHIELD_RESISTED /datum/antagonist/rev/head/on_removal() - if(give_hud) - var/mob/living/carbon/C = owner.current - var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = C.get_organ_slot(ORGAN_SLOT_HUD) - if(S) - S.Remove(C) + if(!give_hud) + return ..() + var/mob/living/carbon/C = owner.current + if (!C) + return ..() + var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = C.get_organ_slot(ORGAN_SLOT_HUD) + if(S) + S.Remove(C) return ..() /datum/antagonist/rev/head/apply_innate_effects(mob/living/mob_override) @@ -310,6 +313,8 @@ to_chat(old_owner, span_userdanger("Revolution has been disappointed of your leader traits! You are a regular revolutionary now!")) /datum/antagonist/rev/farewell() + if(!owner.current) + return owner.current.balloon_alert_to_viewers("deconverted!") if(ishuman(owner.current)) owner.current.visible_message(span_deconversion_message("[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!"), null, null, null, owner.current) @@ -319,7 +324,7 @@ to_chat(owner, span_userdanger("The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.")) /datum/antagonist/rev/head/farewell() - if (deconversion_source == DECONVERTER_STATION_WIN) + if (deconversion_source == DECONVERTER_STATION_WIN || !owner.current) return owner.current.balloon_alert_to_viewers("deconverted!") if((ishuman(owner.current))) diff --git a/code/modules/antagonists/spiders/spiders.dm b/code/modules/antagonists/spiders/spiders.dm index d42f1aea7b3..1dc136461e2 100644 --- a/code/modules/antagonists/spiders/spiders.dm +++ b/code/modules/antagonists/spiders/spiders.dm @@ -29,7 +29,7 @@ explanation_text = "Your queen has given you a directive! Follow it at all costs: [directive]" /datum/objective/spider/check_completion() - return owner.current.stat != DEAD + return owner.current && owner.current.stat != DEAD /datum/antagonist/spider/forge_objectives() var/datum/objective/spider/objective = new(directive) diff --git a/code/modules/antagonists/syndicate_monkey/syndicate_monkey.dm b/code/modules/antagonists/syndicate_monkey/syndicate_monkey.dm index eae5d558a7c..7fb61f6caae 100644 --- a/code/modules/antagonists/syndicate_monkey/syndicate_monkey.dm +++ b/code/modules/antagonists/syndicate_monkey/syndicate_monkey.dm @@ -27,7 +27,7 @@ var/mob/living/monky_master /datum/objective/syndicate_monkey/check_completion() - return monky_master.stat != DEAD + return monky_master && monky_master.stat != DEAD /datum/antagonist/syndicate_monkey/forge_objectives(mob/monky_master) var/datum/objective/syndicate_monkey/objective = new diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 3fc355d91e4..4b7c3a97c58 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -209,7 +209,6 @@ datum_owner.AddComponent(/datum/component/codeword_hearing, GLOB.syndicate_code_response_regex, "red", src) /datum/antagonist/traitor/remove_innate_effects(mob/living/mob_override) - . = ..() var/mob/living/datum_owner = mob_override || owner.current handle_clown_mutation(datum_owner, removing = FALSE) diff --git a/code/modules/antagonists/venus_human_trap/venus_human_trap.dm b/code/modules/antagonists/venus_human_trap/venus_human_trap.dm index c84f20d0596..60e4a282a37 100644 --- a/code/modules/antagonists/venus_human_trap/venus_human_trap.dm +++ b/code/modules/antagonists/venus_human_trap/venus_human_trap.dm @@ -18,7 +18,7 @@ explanation_text = "Spread the infestation." /datum/objective/venus_human_trap/check_completion() - return owner.current.stat != DEAD + return owner.current && owner.current.stat != DEAD /datum/antagonist/venus_human_trap/forge_objectives() var/datum/objective/venus_human_trap/objective = new diff --git a/code/modules/antagonists/voidwalker/voidwalker.dm b/code/modules/antagonists/voidwalker/voidwalker.dm index 3d9b0012555..ba3c2f15c57 100644 --- a/code/modules/antagonists/voidwalker/voidwalker.dm +++ b/code/modules/antagonists/voidwalker/voidwalker.dm @@ -57,4 +57,4 @@ ..() /datum/objective/voidwalker_objective/check_completion() - return owner.current.stat != DEAD + return owner.current && owner.current.stat != DEAD diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm index b60b6498578..da9c36de1b0 100644 --- a/code/modules/antagonists/xeno/xeno.dm +++ b/code/modules/antagonists/xeno/xeno.dm @@ -96,7 +96,7 @@ explanation_text = "Survive and advance the Hive." /datum/objective/advance_hive/check_completion() - return owner.current.stat != DEAD + return owner.current && owner.current.stat != DEAD ///Captive Xenomorphs team /datum/team/xeno/captive