Fix flaky hard delete related to wound-induced brain traumas (#90751)

## About The Pull Request

Brain traumas caused by head wounds are stored as a reference on the
wound, but certain brain traumas (like split personality) `qdel`
themselves in `on_gain()` if conditions aren't valid for them to exist,
`/obj/item/organ/brain/proc/brain_gain_trauma` returns a reference even
if this happens, leading to the ref being stored on the wound and
preventing the trauma from being fully deleted.

## Why It's Good For The Game

Fixes #87752 

## Changelog

No player facing changes

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
This commit is contained in:
Roxy
2025-04-22 15:23:35 -04:00
co-authored by LemonInTheDark
parent a73615e3a1
commit 2a8574c34e
10 changed files with 26 additions and 25 deletions
+1
View File
@@ -42,6 +42,7 @@
to_chat(owner, gain_text)
RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech))
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, PROC_REF(handle_hearing))
return TRUE
//Called when removed from a mob
/datum/brain_trauma/proc/on_lose(silent)
+2 -3
View File
@@ -22,14 +22,13 @@
obsession = find_obsession()
if(!obsession)//we didn't find one
lose_text = ""
qdel(src)
return
return FALSE
gain_text = span_warning("You hear a sickening, raspy voice in your head. It wants one small task of you...")
owner.mind.add_antag_datum(/datum/antagonist/obsessed)
antagonist = owner.mind.has_antag_datum(/datum/antagonist/obsessed)
antagonist.trauma = src
RegisterSignal(obsession, COMSIG_MOB_EYECONTACT, PROC_REF(stare))
..()
. = ..()
//antag stuff//
antagonist.forge_objectives(obsession.mind)
antagonist.greet()
+1 -1
View File
@@ -47,7 +47,7 @@
antagonist.objectives = list(fixation)
hypno_alert.desc = "\"[hypnotic_phrase]\"... your mind seems to be fixated on this concept."
..()
. = ..()
/datum/brain_trauma/hypnosis/on_lose()
message_admins("[ADMIN_LOOKUPFLW(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
+2 -3
View File
@@ -15,9 +15,8 @@
/datum/brain_trauma/special/imaginary_friend/on_gain()
var/mob/living/M = owner
if(M.stat == DEAD || !M.client)
qdel(src)
return
..()
return FALSE
. = ..()
make_friend()
get_ghost()
+1 -1
View File
@@ -62,7 +62,7 @@
/datum/brain_trauma/magic/antimagic/on_gain()
ADD_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/magic/antimagic/on_lose()
REMOVE_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT)
+2 -2
View File
@@ -79,7 +79,7 @@
/datum/brain_trauma/mild/speech_impediment/on_gain()
ADD_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/mild/speech_impediment/on_lose()
REMOVE_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
@@ -167,7 +167,7 @@
/datum/brain_trauma/mild/muscle_spasms/on_gain()
owner.apply_status_effect(/datum/status_effect/spasms)
..()
. = ..()
/datum/brain_trauma/mild/muscle_spasms/on_lose()
owner.remove_status_effect(/datum/status_effect/spasms)
+6 -6
View File
@@ -15,7 +15,7 @@
/datum/brain_trauma/severe/mute/on_gain()
ADD_TRAIT(owner, TRAIT_MUTE, TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/severe/mute/on_lose()
REMOVE_TRAIT(owner, TRAIT_MUTE, TRAUMA_TRAIT)
@@ -31,7 +31,7 @@
/datum/brain_trauma/severe/aphasia/on_gain()
owner.add_blocked_language(subtypesof(/datum/language) - /datum/language/aphasia, LANGUAGE_APHASIA)
owner.grant_language(/datum/language/aphasia, source = LANGUAGE_APHASIA)
..()
. = ..()
/datum/brain_trauma/severe/aphasia/on_lose()
if(!QDELING(owner))
@@ -49,7 +49,7 @@
/datum/brain_trauma/severe/blindness/on_gain()
owner.become_blind(TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/severe/blindness/on_lose()
owner.cure_blind(TRAUMA_TRAIT)
@@ -104,7 +104,7 @@
lose_text = span_notice("You can feel [subject] again!")
/datum/brain_trauma/severe/paralysis/on_gain()
..()
. = ..()
for(var/X in paralysis_traits)
ADD_TRAIT(owner, X, TRAUMA_TRAIT)
@@ -196,7 +196,7 @@
/datum/brain_trauma/severe/pacifism/on_gain()
ADD_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/severe/pacifism/on_lose()
REMOVE_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
@@ -259,7 +259,7 @@
/datum/brain_trauma/severe/dyslexia/on_gain()
ADD_TRAIT(owner, TRAIT_ILLITERATE, TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/severe/dyslexia/on_lose()
REMOVE_TRAIT(owner, TRAIT_ILLITERATE, TRAUMA_TRAIT)
+3 -3
View File
@@ -25,7 +25,7 @@
/datum/brain_trauma/special/godwoken/on_gain()
ADD_TRAIT(owner, TRAIT_HOLY, TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/special/godwoken/on_lose()
REMOVE_TRAIT(owner, TRAIT_HOLY, TRAUMA_TRAIT)
@@ -266,7 +266,7 @@
/datum/brain_trauma/special/tenacity/on_gain()
owner.add_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_ANALGESIA), TRAUMA_TRAIT)
..()
. = ..()
/datum/brain_trauma/special/tenacity/on_lose()
owner.remove_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_ANALGESIA), TRAUMA_TRAIT)
@@ -463,7 +463,7 @@
owner.add_mood_event("combat_ptsd", /datum/mood_event/desentized)
owner.mob_mood?.mood_modifier -= 1 //Basically nothing can change your mood
owner.mob_mood?.sanity_level = SANITY_DISTURBED //Makes sanity on a unstable level unless cured
..()
. = ..()
/datum/brain_trauma/special/ptsd/on_lose()
owner.clear_mood_event("combat_ptsd")
@@ -17,9 +17,8 @@
/datum/brain_trauma/severe/split_personality/on_gain()
var/mob/living/brain_owner = owner
if(brain_owner.stat == DEAD || !GET_CLIENT(brain_owner)) //No use assigning people to a corpse or braindead
qdel(src)
return
..()
return FALSE
. = ..()
make_backseats()
#ifdef UNIT_TESTS
@@ -209,7 +208,7 @@
| strings("ion_laws.json", "iondrinks"))
/datum/brain_trauma/severe/split_personality/brainwashing/on_gain()
..()
. = ..()
var/mob/living/split_personality/traitor/traitor_backseat = stranger_backseat
traitor_backseat.codeword = codeword
traitor_backseat.objective = objective
+5 -2
View File
@@ -98,7 +98,8 @@
continue
trauma.owner = brain_owner
trauma.on_gain()
if(!trauma.on_gain())
qdel(trauma)
//Update the body's icon so it doesnt appear debrained anymore
if(!special && !(brain_owner.living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
@@ -582,7 +583,9 @@
if(SEND_SIGNAL(owner, COMSIG_CARBON_GAIN_TRAUMA, trauma, resilience) & COMSIG_CARBON_BLOCK_TRAUMA)
qdel(actual_trauma)
return FALSE
actual_trauma.on_gain()
if(!actual_trauma.on_gain())
qdel(actual_trauma)
return FALSE
log_game("[key_name_and_tag(owner)] has gained the following brain trauma: [trauma.type]")
if(resilience)
actual_trauma.resilience = resilience