Deprioritise phobias in two sources of random trauma (#88958)

This commit is contained in:
Jacquerel
2025-01-11 21:35:27 +00:00
committed by GitHub
parent 24e07e242a
commit 28e4c83d54
5 changed files with 105 additions and 18 deletions

View File

@@ -356,7 +356,7 @@
owner.cause_hallucination(/datum/hallucination/delusion/preset/heretic, "Caused by The Weeping brain trauma")
owner.add_mood_event("eldritch_weeping", /datum/mood_event/eldritch_painting/weeping)
COOLDOWN_START(src, weeping_hallucinations, 10 SECONDS)
..()
return ..()
//This one is for "The First Desire" or /obj/structure/sign/painting/eldritch/desire
/datum/brain_trauma/severe/flesh_desire
@@ -373,7 +373,7 @@
// Allows them to eat faster, mainly for flavor
ADD_TRAIT(owner, TRAIT_VORACIOUS, REF(src))
ADD_TRAIT(owner, TRAIT_FLESH_DESIRE, REF(src))
..()
return ..()
/datum/brain_trauma/severe/flesh_desire/on_life(seconds_per_tick, times_fired)
// Causes them to need to eat at 10x the normal rate

View File

@@ -624,16 +624,44 @@ Basically, we fill the time between now and 2s from now with hands based off the
return
if(!(SPT_PROB(creation_purity*10, seconds_per_tick)))
return
var/traumalist = subtypesof(/datum/brain_trauma)
var/list/forbiddentraumas = list(
/datum/brain_trauma/severe/split_personality, // Split personality uses a ghost, I don't want to use a ghost for a temp thing
/datum/brain_trauma/special/obsessed, // Obsessed sets the affected_mob as an antag - I presume this will lead to problems, so we'll remove it
/datum/brain_trauma/hypnosis, // Hypnosis, same reason as obsessed, plus a bug makes it remain even after the neurowhine purges and then turn into "nothing" on the med reading upon a second application
/datum/brain_trauma/special/honorbound, // Designed to be chaplain exclusive
)
traumalist -= forbiddentraumas
var/obj/item/organ/brain/brain = affected_mob.get_organ_slot(ORGAN_SLOT_BRAIN)
var/static/list/traumalist
if (!traumalist)
traumalist = subtypesof(/datum/brain_trauma)
// Don't add these to the list because they're abstract category types
var/list/abstracttraumas = list(
/datum/brain_trauma/magic,
/datum/brain_trauma/mild,
/datum/brain_trauma/severe,
/datum/brain_trauma/special,
)
// Don't give out these traumas or any of their descendants
var/list/forbiddentraumas = list(
/datum/brain_trauma/severe/split_personality, // Uses a ghost, I don't want to use a ghost for a temp thing
/datum/brain_trauma/special/imaginary_friend, // Same as above
/datum/brain_trauma/special/obsessed, // Obsessed sets the affected_mob as an antag - I presume this will lead to problems, so we'll remove it
/datum/brain_trauma/hypnosis, // Hypnosis, same reason as obsessed, plus a bug makes it remain even after the neruwhine purges and then turn into "nothing" on the med reading upon a second application
/datum/brain_trauma/severe/hypnotic_stupor, // These apply the above blacklisted trauma
/datum/brain_trauma/severe/hypnotic_trigger,
/datum/brain_trauma/special/honorbound, // Designed to be chaplain exclusive
)
// Do give out these traumas but not any of their subtypes, usually because the trauma replaces itself with a subtype
var/list/forbiddensubtypes = list(
/datum/brain_trauma/mild/phobia,
/datum/brain_trauma/severe/paralysis,
/datum/brain_trauma/special/psychotic_brawling,
)
traumalist -= abstracttraumas
for (var/type as anything in forbiddentraumas)
traumalist -= typesof(type)
for (var/type as anything in forbiddensubtypes)
traumalist -= subtypesof(type)
traumalist = shuffle(traumalist)
var/obj/item/organ/brain/brain = affected_mob.get_organ_slot(ORGAN_SLOT_BRAIN)
for(var/trauma in traumalist)
if(brain.brain_gain_trauma(trauma, TRAUMA_RESILIENCE_MAGIC))
temp_trauma = trauma

View File

@@ -223,18 +223,17 @@
. += mutable_appearance(icon, icon_state = "[icon_state]_shine", appearance_flags = RESET_COLOR|KEEP_APART)
/obj/structure/ethereal_crystal/proc/heal_ethereal()
var/datum/brain_trauma/picked_trauma
if(prob(10)) //10% chance for a severe trauma
picked_trauma = pick(subtypesof(/datum/brain_trauma/severe))
else
picked_trauma = pick(subtypesof(/datum/brain_trauma/mild))
// revive will regenerate organs, so our heart refence is going to be null'd. Unreliable
var/mob/living/carbon/regenerating = ethereal_heart.owner
playsound(get_turf(regenerating), 'sound/mobs/humanoids/ethereal/ethereal_revive.ogg', 100)
to_chat(regenerating, span_notice("You burst out of the crystal with vigour... </span><span class='userdanger'>But at a cost."))
regenerating.gain_trauma(picked_trauma, TRAUMA_RESILIENCE_ABSOLUTE)
if(prob(10)) //10% chance for a severe trauma
regenerating.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_ABSOLUTE)
else
regenerating.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_ABSOLUTE)
regenerating.revive(HEAL_ALL & ~HEAL_REFRESH_ORGANS)
// revive calls fully heal -> deletes the crystal.
// this qdeleted check is just for sanity.

View File

@@ -155,6 +155,7 @@
#include "emoting.dm"
#include "emp_flashlight.dm"
#include "ensure_subtree_operational_datum.dm"
#include "ethereal_revival.dm"
#include "explosion_action.dm"
#include "fish_unit_tests.dm"
#include "focus_only_tests.dm"

View File

@@ -0,0 +1,59 @@
/// Test various permutations of ethereal revival
/datum/unit_test/ethereal_revival
/datum/unit_test/ethereal_revival/Run()
var/mob/living/carbon/human/victim = allocate(/mob/living/carbon/human/consistent)
var/obj/item/organ/heart/ethereal/respawn_heart = new()
respawn_heart.Insert(victim, special = TRUE, movement_flags = DELETE_IF_REPLACED) // Pretend this guy is an ethereal
victim.death()
TEST_ASSERT_NOTNULL(respawn_heart.crystalize_timer_id, "Ethereal heart didn't respond to host death.")
victim.revive()
TEST_ASSERT_NULL(respawn_heart.crystalize_timer_id, "Ethereal heart didn't respond to host revival.")
victim.death()
victim.apply_damage(300)
TEST_ASSERT_NULL(respawn_heart.crystalize_timer_id, "Ethereal heart didn't cancel revival on taking damage.")
instant_crystallise(victim, respawn_heart)
TEST_ASSERT_NOTNULL(respawn_heart.current_crystal, "Ethereal heart didn't successfully crystallise host.")
qdel(respawn_heart.current_crystal)
TEST_ASSERT(respawn_heart.crystalize_cooldown > 0, "Ethereal heart didn't go on cooldown after crystallising.")
TEST_ASSERT(respawn_heart.crystalize_cooldown < INFINITY, "Ethereal heart got stuck on cooldown when crystal was destroyed.")
instant_crystallise(victim, respawn_heart)
TEST_ASSERT_NULL(respawn_heart.current_crystal, "Ethereal crystallised while heart was on cooldown.")
victim.gain_trauma(/datum/brain_trauma/special/ptsd, resilience = TRAUMA_RESILIENCE_BASIC) // One you can't gain via revival
var/obj/item/bodypart/leg/left_leg = victim.get_bodypart(BODY_ZONE_L_LEG)
left_leg.dismember()
var/obj/item/bodypart/leg/right_leg = victim.get_bodypart(BODY_ZONE_R_LEG)
var/datum/wound/slash/flesh/severe/crit_wound = new()
crit_wound.apply_wound(right_leg)
kill_and_revive(victim, respawn_heart)
TEST_ASSERT(victim.health == victim.maxHealth, "Ethereal not fully healed after reviving.")
TEST_ASSERT_NOTNULL(victim.get_bodypart(BODY_ZONE_L_LEG), "Ethereal failed to regrow limb when reviving.")
TEST_ASSERT(!length(right_leg.wounds), "Ethereal failed to fix wound when reviving.")
var/list/current_traumas = victim.get_traumas()
TEST_ASSERT(!(locate(/datum/brain_trauma/special/ptsd) in current_traumas), "Ethereal failed to heal curable brain trauma when reviving.")
TEST_ASSERT(length(current_traumas) == 1, "Ethereal failed to gain trauma when reviving.")
kill_and_revive(victim, respawn_heart)
TEST_ASSERT(length(victim.get_traumas()) == 2, "Ethereal failed to gain additional trauma on second revival.")
instant_crystallise(victim, respawn_heart)
victim.heal_and_revive()
TEST_ASSERT_NULL(respawn_heart.current_crystal, "Crystal didn't despawn when player was revived by other means.")
/datum/unit_test/ethereal_revival/proc/instant_crystallise(mob/living/carbon/victim, obj/item/organ/heart/ethereal/respawn_heart)
victim.death()
deltimer(respawn_heart.crystalize_timer_id)
respawn_heart.crystalize(victim)
/datum/unit_test/ethereal_revival/proc/kill_and_revive(mob/living/carbon/victim, obj/item/organ/heart/ethereal/respawn_heart)
COOLDOWN_RESET(respawn_heart, crystalize_cooldown)
instant_crystallise(victim, respawn_heart)
var/obj/structure/ethereal_crystal/crystal = respawn_heart.current_crystal
crystal.heal_ethereal()