diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
index 4922c80f9d1..401255a160d 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm
@@ -381,3 +381,6 @@
/// Sent to a mob when one of their bodypart's surgery state changes, OR sent from the basic_surgery_state holder when its surgery state changes (old_state, new_state, changed_states)
#define COMSIG_LIVING_UPDATING_SURGERY_STATE "carbon_updating_surgery_state"
+
+/// Sent to a mob when its player DNRs
+#define COMSIG_LIVING_DNR "living_dnr"
diff --git a/code/__DEFINES/quirks.dm b/code/__DEFINES/quirks.dm
index 8cc1dee678b..41b2882e37e 100644
--- a/code/__DEFINES/quirks.dm
+++ b/code/__DEFINES/quirks.dm
@@ -17,3 +17,5 @@
/// Quirk is similar to brain trauma and should be shown in medical guides as one.
/// You don't need to set this on quirks that apply a trauma, that's redundant.
#define QUIRK_TRAUMALIKE (1<<5)
+/// Do not transfer this quirk via transfer_quirk_datums
+#define QUIRK_NO_TRANSFER (1<<6)
diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index 8365b5a58ed..dea44f55315 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -1597,9 +1597,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Trait that signals to objects on this turf that its open (has UNDERFLOOR_INTERACTIBLE) but still covers them
#define TRAIT_UNCOVERED_TURF "uncovered_turf"
-/// A trait that blocks the metabolism of formaldehyde
-#define TRAIT_BLOCK_FORMALDEHYDE_METABOLISM "block_formaldehyde_metabolism"
-
///Attached to objects currently on tables and such, allowing them to walk on other objects without the climbing delay
#define TRAIT_ON_CLIMBABLE "on_climbable"
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 8f46c495437..58afc53aff7 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -195,7 +195,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BIRTHDAY_BOY" = TRAIT_BIRTHDAY_BOY,
"TRAIT_BLOB_ALLY" = TRAIT_BLOB_ALLY,
"TRAIT_BLOCKING_PROJECTILES" = TRAIT_BLOCKING_PROJECTILES,
- "TRAIT_BLOCK_FORMALDEHYDE_METABOLISM" = TRAIT_BLOCK_FORMALDEHYDE_METABOLISM,
"TRAIT_BLOCK_SECHUD" = TRAIT_BLOCK_SECHUD,
"TRAIT_BLOCK_SHUTTLE_MOVEMENT" = TRAIT_BLOCK_SHUTTLE_MOVEMENT,
"TRAIT_BLOODSHOT_EYES" = TRAIT_BLOODSHOT_EYES,
diff --git a/code/datums/components/ghostrole_on_revive.dm b/code/datums/components/ghostrole_on_revive.dm
index a8930831c88..52ea1d0bd07 100644
--- a/code/datums/components/ghostrole_on_revive.dm
+++ b/code/datums/components/ghostrole_on_revive.dm
@@ -6,14 +6,31 @@
var/datum/callback/on_successful_revive
/// The chance to twitch when orbiting the spawn
var/twitch_chance = 30
+ /// The title shown to ghosts when polled to enter the body
+ var/revive_title
-/datum/component/ghostrole_on_revive/Initialize(refuse_revival_if_failed, on_successful_revive)
- . = ..()
+ // Text displayed in the spawners menu
+ var/spawn_text
+ var/you_are_text
+ var/flavor_text
+ var/important_text
+/datum/component/ghostrole_on_revive/Initialize(
+ refuse_revival_if_failed = FALSE,
+ datum/callback/on_successful_revive,
+ revive_title = "a recovered crewmember",
+ spawn_text = "Recovered Crew",
+ you_are_text = "You are a long dead crewmember, but are soon to be revived to rejoin the crew!",
+ flavor_text = "Get a job and get back to work!",
+ important_text = "Do your best to help the station. You still roll for midround antagonists."
+)
src.refuse_revival_if_failed = refuse_revival_if_failed
src.on_successful_revive = on_successful_revive
-
- ADD_TRAIT(parent, TRAIT_GHOSTROLE_ON_REVIVE, REF(src)) //for adding an alternate examination
+ src.revive_title = revive_title
+ src.spawn_text = spawn_text
+ src.you_are_text = you_are_text
+ src.flavor_text = flavor_text
+ src.important_text = important_text
if(ismob(parent))
prepare_mob(parent)
@@ -22,138 +39,152 @@
if(!istype(parent, /obj/item/organ/brain))
return COMPONENT_INCOMPATIBLE
- var/obj/item/organ/brain/brein = parent
- if(brein.owner)
- prepare_mob(brein.owner)
+ var/obj/item/organ/brain/brain_parent = parent
+ if(brain_parent.owner)
+ prepare_mob(brain_parent.owner)
else
- prepare_brain(brein)
+ prepare_brain(brain_parent)
/// Give the appropriate signals, and watch for organ removal
-/datum/component/ghostrole_on_revive/proc/prepare_mob(mob/living/liver)
- RegisterSignal(liver, COMSIG_LIVING_REVIVE, PROC_REF(on_revive))
- ADD_TRAIT(liver, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
+/datum/component/ghostrole_on_revive/proc/prepare_mob(mob/living/to_prepare)
+ RegisterSignal(to_prepare, COMSIG_LIVING_REVIVE, PROC_REF(on_revive))
+ RegisterSignal(to_prepare, COMSIG_MOB_REAGENT_TICK, PROC_REF(block_formaldehyde_metabolism))
+ if(istype(parent, /obj/item/organ/brain))
+ RegisterSignal(to_prepare, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(on_remove))
+ ADD_TRAIT(to_prepare, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
- add_orbit_twitching(liver)
+ add_orbit_twitching(to_prepare)
+ to_prepare.med_hud_set_status()
- liver.med_hud_set_status()
+/datum/component/ghostrole_on_revive/proc/unprepare_mob(mob/living/to_unprepare)
+ REMOVE_TRAIT(to_unprepare, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
+ UnregisterSignal(to_unprepare, list(
+ COMSIG_LIVING_REVIVE,
+ COMSIG_MOB_REAGENT_TICK,
+ COMSIG_CARBON_LOSE_ORGAN,
+ ))
- if(iscarbon(liver))
- var/mob/living/carbon/carbon = liver
- var/obj/item/organ/brain = carbon.get_organ_by_type(/obj/item/organ/brain)
- if(brain)
- RegisterSignal(brain, COMSIG_ORGAN_REMOVED, PROC_REF(on_remove))
+ to_unprepare.med_hud_set_status()
+ remove_orbit_twitching(to_unprepare)
-/datum/component/ghostrole_on_revive/proc/on_remove(obj/item/organ/brain, mob/living/old_owner)
+/datum/component/ghostrole_on_revive/proc/on_remove(mob/living/carbon/source, obj/item/organ/removed_brain)
SIGNAL_HANDLER
- REMOVE_TRAIT(old_owner, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
- remove_orbit_twitching(old_owner)
+ if(!istype(removed_brain, /obj/item/organ/brain))
+ return
+
+ unprepare_mob(source)
// we might have some lingering blinking eyes
- var/obj/item/bodypart/head/head = old_owner?.get_bodypart(BODY_ZONE_HEAD)
+ var/obj/item/bodypart/head/head = source.get_bodypart(BODY_ZONE_HEAD)
if(head)
var/soul_eyes = locate(/datum/bodypart_overlay/simple/soul_pending_eyes) in head.bodypart_overlays
if(soul_eyes)
head.remove_bodypart_overlay(soul_eyes)
- prepare_brain(brain)
+ prepare_brain(removed_brain)
-/datum/component/ghostrole_on_revive/proc/prepare_brain(obj/item/organ/brein)
+/datum/component/ghostrole_on_revive/proc/prepare_brain(obj/item/organ/source)
+ ADD_TRAIT(source, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
+ RegisterSignal(source, COMSIG_ORGAN_IMPLANTED, PROC_REF(prepare_mob_from_brain))
+ UnregisterSignal(source, COMSIG_ORGAN_REMOVED)
+
+/datum/component/ghostrole_on_revive/proc/unprepare_brain(obj/item/organ/source)
+ REMOVE_TRAIT(source, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
+ UnregisterSignal(source, COMSIG_ORGAN_IMPLANTED)
+ RegisterSignal(source, COMSIG_ORGAN_REMOVED, PROC_REF(prepare_brain))
+ source.owner?.med_hud_set_status()
+
+/datum/component/ghostrole_on_revive/proc/prepare_mob_from_brain(obj/item/organ/brain/source, mob/living/owner)
SIGNAL_HANDLER
- RegisterSignal(brein, COMSIG_ORGAN_IMPLANTED, PROC_REF(prepare_mob_from_brain))
- UnregisterSignal(brein, COMSIG_ORGAN_REMOVED)
-
-/datum/component/ghostrole_on_revive/proc/prepare_mob_from_brain(obj/item/organ/brain/brein, mob/living/owner)
- SIGNAL_HANDLER
-
- UnregisterSignal(brein, COMSIG_ORGAN_IMPLANTED)
+ REMOVE_TRAIT(source, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
+ UnregisterSignal(source, COMSIG_ORGAN_IMPLANTED)
prepare_mob(owner)
-/datum/component/ghostrole_on_revive/proc/on_revive(mob/living/aliver)
+/datum/component/ghostrole_on_revive/proc/on_revive(mob/living/source)
SIGNAL_HANDLER
- INVOKE_ASYNC(src, PROC_REF(poll_ghosts), aliver)
+ INVOKE_ASYNC(src, PROC_REF(poll_ghosts), source)
-/datum/component/ghostrole_on_revive/proc/poll_ghosts(mob/living/aliver)
- var/soul_eyes
- var/obj/item/bodypart/head
+/datum/component/ghostrole_on_revive/proc/poll_ghosts(mob/living/reviving)
+ var/datum/bodypart_overlay/simple/soul_pending_eyes/soul_eyes
// adds soulful SOUL PENDING eyes to indicate what's happening to observers
+ var/obj/item/bodypart/head/head = reviving.get_bodypart(BODY_ZONE_HEAD)
+ if(head)
+ soul_eyes = new()
+ head.add_bodypart_overlay(soul_eyes)
- var/mob/living/carbon/human/hewmon
- if(ishuman(aliver))
- hewmon = aliver
- head = hewmon.get_bodypart(BODY_ZONE_HEAD)
- if(head)
- soul_eyes = new /datum/bodypart_overlay/simple/soul_pending_eyes()
- head.add_bodypart_overlay(soul_eyes)
-
- // So during the potentially short period of time we're revived, we don't metabolize formaldehyde
- // Really just a QOL for coroners, so we dont suddenly start decaying
- ADD_TRAIT(aliver, TRAIT_BLOCK_FORMALDEHYDE_METABOLISM, type)
+ var/list/jobbans = list(ROLE_RECOVERED_CREW)
+ if(reviving.mind)
+ jobbans |= reviving.mind.assigned_role.title
+ for(var/datum/antagonist/antag as anything in reviving.mind.antag_datums)
+ if(antag.jobban_flag)
+ jobbans |= antag.jobban_flag
+ if(antag.pref_flag)
+ jobbans |= antag.pref_flag
+ if(!(antag.antag_flags & ANTAG_FAKE))
+ jobbans |= ROLE_SYNDICATE
var/mob/dead/observer/chosen_one = SSpolling.poll_ghosts_for_target(
- question = "Would you like to play as a recovered crewmember?",
- role = null,
- check_jobban = ROLE_RECOVERED_CREW,
+ question = "Would you like to play as [revive_title]?",
+ check_jobban = jobbans,
poll_time = 15 SECONDS,
- checked_target = aliver,
+ checked_target = reviving,
ignore_category = POLL_IGNORE_RECOVERED_CREW,
- alert_pic = aliver,
- role_name_text = "recovered crew",
+ alert_pic = reviving,
+ role_name_text = revive_title,
)
- REMOVE_TRAIT(aliver, TRAIT_BLOCK_FORMALDEHYDE_METABOLISM, type)
-
if(head)
head.remove_bodypart_overlay(soul_eyes)
+ if(soul_eyes)
+ qdel(soul_eyes)
- if(!isobserver(chosen_one))
- if(refuse_revival_if_failed)
- aliver.death()
- aliver.visible_message(span_deadsay("[aliver.name]'s soul is struggling to return!"))
- else
- aliver.PossessByPlayer(chosen_one.ckey)
- on_successful_revive?.Invoke(aliver)
+ if(isobserver(chosen_one))
+ reviving.PossessByPlayer(chosen_one.ckey)
+ on_successful_revive?.Invoke(reviving)
qdel(src)
-/datum/component/ghostrole_on_revive/proc/add_orbit_twitching(mob/living/liver)
- liver.AddElement(/datum/element/orbit_twitcher, twitch_chance)
+ else if(refuse_revival_if_failed)
+ reviving.death()
+ reviving.visible_message(span_deadsay("[reviving]'s soul is struggling to return!"))
+
+/datum/component/ghostrole_on_revive/proc/add_orbit_twitching(mob/living/parent_mob)
+ parent_mob.AddElement(/datum/element/orbit_twitcher, twitch_chance)
// Add it to the ghostrole spawner menu. Note that we can't directly spawn from it, but we can make it twitch to alert bystanders to defib it
- LAZYADD(GLOB.joinable_mobs[format_text("Recovered Crew")], liver)
- RegisterSignal(liver, COMSIG_LIVING_GHOSTROLE_INFO, PROC_REF(set_spawner_info))
+ LAZYADDASSOCLIST(GLOB.joinable_mobs, spawn_text, parent_mob)
+ RegisterSignal(parent_mob, COMSIG_LIVING_GHOSTROLE_INFO, PROC_REF(set_spawner_info))
-/datum/component/ghostrole_on_revive/proc/set_spawner_info(datum/spawners_menu/menu, string_info)
+/datum/component/ghostrole_on_revive/proc/set_spawner_info(datum/spawners_menu/menu, list/string_info)
SIGNAL_HANDLER
- string_info["you_are_text"] = "You are a long dead crewmember, but are soon to be revived to rejoin the crew!"
- string_info["flavor_text"] = "Get a job and get back to work!"
- string_info["important_text"] = "Do your best to help the station. You still roll for midround antagonists."
+ string_info["you_are_text"] = src.you_are_text
+ string_info["flavor_text"] = src.flavor_text
+ string_info["important_text"] = src.important_text
-/datum/component/ghostrole_on_revive/proc/remove_orbit_twitching(mob/living/living)
- living.RemoveElement(/datum/element/orbit_twitcher, twitch_chance)
+/datum/component/ghostrole_on_revive/proc/remove_orbit_twitching(mob/living/parent_mob)
+ parent_mob.RemoveElement(/datum/element/orbit_twitcher, twitch_chance)
+ LAZYREMOVEASSOC(GLOB.joinable_mobs, spawn_text, parent_mob)
+ UnregisterSignal(parent_mob, COMSIG_LIVING_GHOSTROLE_INFO)
- // Remove from the ghostrole spawning menu
- var/list/spawners = GLOB.joinable_mobs[format_text("Recovered Crew")]
- LAZYREMOVE(spawners, living)
+// Block formaldehyde from being metabolized, Coroner QoL
+/datum/component/ghostrole_on_revive/proc/block_formaldehyde_metabolism(mob/living/source, datum/reagent/chem)
+ SIGNAL_HANDLER
- if(!LAZYLEN(spawners))
- GLOB.joinable_mobs -= format_text("Recovered Crew")
-
- UnregisterSignal(living, COMSIG_LIVING_GHOSTROLE_INFO)
+ if(istype(chem, /datum/reagent/toxin/formaldehyde))
+ return COMSIG_MOB_STOP_REAGENT_TICK
/datum/component/ghostrole_on_revive/Destroy(force)
- REMOVE_TRAIT(parent, TRAIT_GHOSTROLE_ON_REVIVE, REF(src))
-
- var/mob/living/living
if(isliving(parent))
- living = parent
+ unprepare_mob(parent)
+
else if(istype(parent, /obj/item/organ/brain))
var/obj/item/organ/brain/brain = parent
- living = brain.owner
- living?.med_hud_set_status()
- if(living)
- remove_orbit_twitching(living)
+ if(brain.owner)
+ unprepare_mob(brain.owner)
+ else
+ unprepare_brain(brain)
return ..()
diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm
index e8d6748faa3..46be5ac25a5 100644
--- a/code/datums/quirks/_quirk.dm
+++ b/code/datums/quirks/_quirk.dm
@@ -286,5 +286,7 @@
var/datum/preferences/to_pass = client || to_mob.client
for(var/datum/quirk/quirk as anything in quirks)
+ if(quirk.quirk_flags & QUIRK_NO_TRANSFER)
+ continue
quirk.remove_from_current_holder(quirk_transfer = TRUE)
quirk.add_to_holder(to_mob, quirk_transfer = TRUE, client_source = to_pass)
diff --git a/code/datums/quirks/neutral_quirks/thanatorenasia.dm b/code/datums/quirks/neutral_quirks/thanatorenasia.dm
new file mode 100644
index 00000000000..6b2d1303fb8
--- /dev/null
+++ b/code/datums/quirks/neutral_quirks/thanatorenasia.dm
@@ -0,0 +1,55 @@
+/datum/quirk/death_dnr_poll
+ name = "Thanatorenasia"
+ desc = "Whenever you die and elect to \"Do Not Resuscitate\", your body may be taken over by another ghost upon revival - \
+ giving it an entirely new personality and fresh set of memories."
+ icon = FA_ICON_ZAP
+ value = 0
+ medical_record_text = "Patient has Thanatorenasia - in the event of their death and resuscitation, \
+ they may experience memory loss or a change in personality."
+ medical_symptom_text = "In the event of the patient's death and resuscitation, \
+ they may experience memory loss or a change in personality."
+ quirk_flags = QUIRK_NO_TRANSFER
+
+ // Used the the spawners menu to describe the quirk
+ var/you_are_text = "You are a deceased crewmember, afflicted with Thanatorenasia - \
+ a condition which alters personality and causes memory loss upon death and revival."
+ var/flavor_text = "Something feels... different. \
+ You're not entirely sure who you are or what happened - All you remember is your name and that you work here. \
+ Oh well, better get back to work - the last thing you want is to be both unemployed AND an amnesiac."
+ var/important_text = "Resume your assigned duty. \
+ If you choose to \"Do Not Resuscitate\" upon death, another ghost will be allowed to take over the body. \
+ You still roll for midround antagonists."
+
+/datum/quirk/death_dnr_poll/add_unique(client/client_source)
+ . = ..()
+ RegisterSignal(quirk_holder, COMSIG_LIVING_DNR, PROC_REF(mob_died))
+
+/datum/quirk/death_dnr_poll/remove()
+ . = ..()
+ UnregisterSignal(quirk_holder, COMSIG_LIVING_DNR)
+
+/datum/quirk/death_dnr_poll/proc/mob_died(mob/living/source, mob/dead/observer/dnring)
+ SIGNAL_HANDLER
+
+ var/whomst = source.real_name
+ if(source.mind && !is_unassigned_job(source.mind.assigned_role))
+ whomst += "Job: [span_notice(source.mind.assigned_role.title)]."
+ if(length(source.mind?.get_special_roles()))
+ whomst += "Status: [span_boldnotice(english_list(source.mind?.get_special_roles()))]."
+
+ source.AddComponent(/datum/component/ghostrole_on_revive, \
+ refuse_revival_if_failed = TRUE, \
+ on_successful_revive = CALLBACK(src, PROC_REF(on_successful_revive)), \
+ revive_title = whomst, \
+ spawn_text = "Deceased Crew", \
+ you_are_text = src.you_are_text, \
+ flavor_text = src.flavor_text, \
+ important_text = src.important_text, \
+ )
+ source.log_message("was made ghostrole pollable by [name] quirk.", LOG_GAME, color = COLOR_PURPLE)
+
+/datum/quirk/death_dnr_poll/proc/on_successful_revive()
+ quirk_holder.log_message("has had their body taken over by a ghost due to the [name] quirk.", LOG_GAME, color = COLOR_PURPLE)
+ var/welcome_msg = boxed_message(span_notice("[quirk_holder.real_name] has [name] - you are [quirk_holder.p_their()] new owner.
\
+ If you choose to \"Do Not Resuscitate\" upon death, another ghost will take over the body once again."))
+ addtimer(CALLBACK(src, GLOBAL_PROC_REF(to_chat), quirk_holder, welcome_msg), 2 SECONDS)
diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm
index b6adf6782e6..1c91fbd48da 100644
--- a/code/datums/spawners_menu.dm
+++ b/code/datums/spawners_menu.dm
@@ -50,9 +50,10 @@
this["name"] = mob_type
this["amount_left"] = 0
for(var/mob/joinable_mob as anything in GLOB.joinable_mobs[mob_type])
+ SEND_SIGNAL(joinable_mob, COMSIG_LIVING_GHOSTROLE_INFO, this)
this["amount_left"] += 1
- if(!SEND_SIGNAL(joinable_mob, COMSIG_LIVING_GHOSTROLE_INFO, this))
- this["desc"] = initial(joinable_mob.desc)
+ this["desc"] ||= initial(joinable_mob.desc)
+
if(this["amount_left"] > 0)
data["spawners"] += list(this)
return data
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index e8e26e5de0a..80d383faba9 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -410,6 +410,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
// Update med huds
current_mob.med_hud_set_status()
current_mob.log_message("had their player ([key_name(src)]) do-not-resuscitate / DNR", LOG_GAME, color = COLOR_GREEN, log_globally = FALSE)
+ SEND_SIGNAL(current_mob, COMSIG_LIVING_DNR, src)
+
log_message("has opted to do-not-resuscitate / DNR from their body ([current_mob])", LOG_GAME, color = COLOR_GREEN)
// Disassociates observer mind from the body mind
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 279e65b8355..6dc3007864c 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -237,7 +237,7 @@
var/obj/item/organ/brain/brain = get_organ_by_type(/obj/item/organ/brain)
if(brain && isnull(ai_controller))
var/npc_message = ""
- if(HAS_TRAIT(brain, TRAIT_GHOSTROLE_ON_REVIVE))
+ if(HAS_TRAIT(brain, TRAIT_GHOSTROLE_ON_REVIVE) || HAS_TRAIT(src, TRAIT_GHOSTROLE_ON_REVIVE))
npc_message = "Soul is pending..."
else if(!key)
npc_message = "[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely."
@@ -324,7 +324,7 @@
var/t_is = p_are()
//This checks to see if the body is revivable
var/obj/item/organ/brain = get_organ_by_type(/obj/item/organ/brain)
- if(brain && HAS_TRAIT(brain, TRAIT_GHOSTROLE_ON_REVIVE))
+ if((brain && HAS_TRAIT(brain, TRAIT_GHOSTROLE_ON_REVIVE)) || HAS_TRAIT(src, TRAIT_GHOSTROLE_ON_REVIVE))
return span_deadsay("[t_He] [t_is] limp and unresponsive; but [t_his] soul might yet come back...")
var/client_like = client || HAS_TRAIT(src, TRAIT_MIND_TEMPORARILY_GONE)
var/valid_ghost = ghost?.can_reenter_corpse && ghost?.client
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 4c95b21afe7..41cba75b8bc 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -785,17 +785,11 @@
if(affected_mob.adjust_tox_loss(-1 * metabolization_ratio * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype)) //it counteracts its own toxin damage.
return UPDATE_MOB_HEALTH
return
- else if(SPT_PROB(2.5, seconds_per_tick) && !HAS_TRAIT(affected_mob, TRAIT_BLOCK_FORMALDEHYDE_METABOLISM))
+ else if(SPT_PROB(2.5, seconds_per_tick))
holder.add_reagent(/datum/reagent/toxin/histamine, pick(5,15))
holder.remove_reagent(/datum/reagent/toxin/formaldehyde, 2.4 * metabolization_ratio * seconds_per_tick)
return ..()
-/datum/reagent/toxin/formaldehyde/metabolize_reagent(mob/living/carbon/affected_mob, seconds_per_tick, metabolized_volume)
- if(HAS_TRAIT(affected_mob, TRAIT_BLOCK_FORMALDEHYDE_METABOLISM))
- return
-
- return ..()
-
/datum/reagent/toxin/venom
name = "Venom"
description = "An exotic poison extracted from highly toxic fauna. Causes scaling amounts of toxin damage and bruising depending and dosage. Often decays into Histamine."
diff --git a/tgstation.dme b/tgstation.dme
index b28377361c5..a815bb3c542 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1953,6 +1953,7 @@
#include "code\datums\quirks\neutral_quirks\pineapple_hater.dm"
#include "code\datums\quirks\neutral_quirks\pineapple_liker.dm"
#include "code\datums\quirks\neutral_quirks\shifty_eyes.dm"
+#include "code\datums\quirks\neutral_quirks\thanatorenasia.dm"
#include "code\datums\quirks\neutral_quirks\transhumanist.dm"
#include "code\datums\quirks\neutral_quirks\vegetarian.dm"
#include "code\datums\quirks\positive_quirks\alcohol_tolerance.dm"