mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 00:58:26 +01:00
Completely refactors hallucinations, and also adds a few (#69706)
* Refactors hallucinations slightly, organizes them * Refactors hallucination into a status effect * Further hallucination proper refactoring * Refactors battle hallucinations * Refactors "fake item other" hallucination * Gets it a bit closer to working state * Refactors screwydoll and fake alerts * Refactors fake inhand items * Refactors a few more. - Fake death - Fake messages - Fake sounds - Projectiles * Refactoring delusions, hallucination effects * Furthering the hallucination status effect - removes copypaste of hallucination pulses * Almost finalizes the changeover to status effect * Last staus effect stuff * Delusion business * Airlocks, fire, and more delusion stuff * Finishes screwyhud. It compiles now! * Swaps screwyhud over to a grouped status effect * Removes hal_screwyhud * Comment * Bugfixing * image cleaning * Get rid of this it came back * What if I finished this branch? * Oops * Messing with the randomness * Mass hallucination tweaks * + * Some more mass tweaks * Review * Updates * Unit tests hallucination icons * More tweaks * Move folder * Another re-name * Minor tweaks * Anomaly unity * Mass hallucination buffs * t * Sig * Merge * Lints * Unit test already coming in clutch * Another failure * Use named args for cause_hallucination via some define trickery * Some cleanup * This is better * adds some hallucinations * Oops * More sounds * Tweaks * Some additional documentation * Flash * Fixes mass hallucination * Json changes * Updates documentation * Json conflicts * Makes it work * Missed that one too * Helpers * More signalization (WIP) * Fixes bump * Missed a helper use * Dumb
This commit is contained in:
@@ -58,11 +58,15 @@
|
||||
/datum/brain_trauma/hypnosis/on_life(delta_time, times_fired)
|
||||
..()
|
||||
if(DT_PROB(1, delta_time))
|
||||
switch(rand(1,2))
|
||||
if(1)
|
||||
to_chat(owner, span_hypnophrase("<i>...[lowertext(hypnotic_phrase)]...</i>"))
|
||||
if(2)
|
||||
new /datum/hallucination/chat(owner, TRUE, FALSE, span_hypnophrase("[hypnotic_phrase]"))
|
||||
if(prob(50))
|
||||
to_chat(owner, span_hypnophrase("<i>...[lowertext(hypnotic_phrase)]...</i>"))
|
||||
else
|
||||
owner.cause_hallucination( \
|
||||
/datum/hallucination/chat, \
|
||||
"hypnosis", \
|
||||
force_radio = TRUE, \
|
||||
specific_message = span_hypnophrase("[hypnotic_phrase]"), \
|
||||
)
|
||||
|
||||
/datum/brain_trauma/hypnosis/handle_hearing(datum/source, list/hearing_args)
|
||||
hearing_args[HEARING_RAW_MESSAGE] = target_phrase.Replace(hearing_args[HEARING_RAW_MESSAGE], span_hypnophrase("$1"))
|
||||
|
||||
@@ -73,12 +73,16 @@
|
||||
scan_desc = "extra-sensory paranoia"
|
||||
gain_text = "<span class='warning'>You feel like something wants to kill you...</span>"
|
||||
lose_text = "<span class='notice'>You no longer feel eyes on your back.</span>"
|
||||
var/obj/effect/hallucination/simple/stalker_phantom/stalker
|
||||
var/obj/effect/client_image_holder/stalker_phantom/stalker
|
||||
var/close_stalker = FALSE //For heartbeat
|
||||
|
||||
/datum/brain_trauma/magic/stalker/Destroy()
|
||||
QDEL_NULL(stalker)
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/magic/stalker/on_gain()
|
||||
create_stalker()
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/magic/stalker/proc/create_stalker()
|
||||
var/turf/stalker_source = locate(owner.x + pick(-12, 12), owner.y + pick(-12, 12), owner.z) //random corner
|
||||
@@ -86,7 +90,7 @@
|
||||
|
||||
/datum/brain_trauma/magic/stalker/on_lose()
|
||||
QDEL_NULL(stalker)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/magic/stalker/on_life(delta_time, times_fired)
|
||||
// Dead and unconscious people are not interesting to the psychic stalker.
|
||||
@@ -115,7 +119,7 @@
|
||||
close_stalker = FALSE
|
||||
..()
|
||||
|
||||
/obj/effect/hallucination/simple/stalker_phantom
|
||||
/obj/effect/client_image_holder/stalker_phantom
|
||||
name = "???"
|
||||
desc = "It's coming closer..."
|
||||
image_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi'
|
||||
|
||||
@@ -8,16 +8,20 @@
|
||||
name = "Hallucinations"
|
||||
desc = "Patient suffers constant hallucinations."
|
||||
scan_desc = "schizophrenia"
|
||||
gain_text = "<span class='warning'>You feel your grip on reality slipping...</span>"
|
||||
lose_text = "<span class='notice'>You feel more grounded.</span>"
|
||||
gain_text = span_warning("You feel your grip on reality slipping...")
|
||||
lose_text = span_notice("You feel more grounded.")
|
||||
|
||||
/datum/brain_trauma/mild/hallucinations/on_life(delta_time, times_fired)
|
||||
owner.hallucination = min(owner.hallucination + 10, 50)
|
||||
..()
|
||||
if(owner.stat != CONSCIOUS || owner.IsSleeping() || owner.IsUnconscious())
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_HALLUCINATION_SUPPRESSED))
|
||||
return
|
||||
|
||||
owner.adjust_hallucinations_up_to(10 SECONDS * delta_time, 100 SECONDS)
|
||||
|
||||
/datum/brain_trauma/mild/hallucinations/on_lose()
|
||||
owner.hallucination = 0
|
||||
..()
|
||||
owner.remove_status_effect(/datum/status_effect/hallucination)
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/mild/stuttering
|
||||
name = "Stuttering"
|
||||
@@ -109,17 +113,15 @@
|
||||
lose_text = "<span class='warning'>You no longer feel perfectly healthy.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/healthy/on_gain()
|
||||
owner.set_screwyhud(SCREWYHUD_HEALTHY)
|
||||
..()
|
||||
owner.apply_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy, type)
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/mild/healthy/on_life(delta_time, times_fired)
|
||||
owner.set_screwyhud(SCREWYHUD_HEALTHY) //just in case of hallucinations
|
||||
owner.adjustStaminaLoss(-2.5 * delta_time) //no pain, no fatigue
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/healthy/on_lose()
|
||||
owner.set_screwyhud(SCREWYHUD_NONE)
|
||||
..()
|
||||
owner.remove_status_effect(/datum/status_effect/grouped/screwy_hud/fake_healthy, type)
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/mild/muscle_weakness
|
||||
name = "Muscle Weakness"
|
||||
|
||||
@@ -200,7 +200,7 @@
|
||||
if(3, 4)
|
||||
if(high_stress)
|
||||
to_chat(owner, span_warning("You're going mad with loneliness!"))
|
||||
owner.hallucination += 30
|
||||
owner.adjust_hallucinations(60 SECONDS)
|
||||
else
|
||||
to_chat(owner, span_warning("You feel really lonely..."))
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
scan_desc = "dyslexia"
|
||||
gain_text = "<span class='warning'>You have trouble reading or writing...</span>"
|
||||
lose_text = "<span class='notice'>Your suddenly remember how to read and write.</span>"
|
||||
|
||||
|
||||
/datum/brain_trauma/severe/dyslexia/on_gain()
|
||||
ADD_TRAIT(owner, TRAIT_ILLITERATE, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
@@ -87,61 +87,64 @@
|
||||
if(!second_turf)
|
||||
return
|
||||
|
||||
var/obj/effect/hallucination/simple/bluespace_stream/first = new(first_turf, owner)
|
||||
var/obj/effect/hallucination/simple/bluespace_stream/second = new(second_turf, owner)
|
||||
var/obj/effect/client_image_holder/bluespace_stream/first = new(first_turf, owner)
|
||||
var/obj/effect/client_image_holder/bluespace_stream/second = new(second_turf, owner)
|
||||
|
||||
first.linked_to = second
|
||||
second.linked_to = first
|
||||
first.seer = owner
|
||||
second.seer = owner
|
||||
|
||||
/obj/effect/hallucination/simple/bluespace_stream
|
||||
/obj/effect/client_image_holder/bluespace_stream
|
||||
name = "bluespace stream"
|
||||
desc = "You see a hidden pathway through bluespace..."
|
||||
image_icon = 'icons/effects/effects.dmi'
|
||||
image_state = "bluestream"
|
||||
image_layer = ABOVE_MOB_LAYER
|
||||
image_plane = GAME_PLANE_UPPER
|
||||
var/obj/effect/hallucination/simple/bluespace_stream/linked_to
|
||||
var/mob/living/carbon/seer
|
||||
var/obj/effect/client_image_holder/bluespace_stream/linked_to
|
||||
|
||||
/obj/effect/hallucination/simple/bluespace_stream/Initialize(mapload)
|
||||
/obj/effect/client_image_holder/bluespace_stream/Initialize(mapload, list/mobs_which_see_us)
|
||||
. = ..()
|
||||
QDEL_IN(src, 300)
|
||||
QDEL_IN(src, 30 SECONDS)
|
||||
|
||||
/obj/effect/hallucination/simple/bluespace_stream/Destroy()
|
||||
/obj/effect/client_image_holder/bluespace_stream/Destroy()
|
||||
if(!QDELETED(linked_to))
|
||||
qdel(linked_to)
|
||||
linked_to = null
|
||||
seer = null
|
||||
return ..()
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/hallucination/simple/bluespace_stream/attack_hand(mob/user, list/modifiers)
|
||||
if(user != seer || !linked_to)
|
||||
/obj/effect/client_image_holder/bluespace_stream/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(!(user in who_sees_us) || !linked_to)
|
||||
return
|
||||
|
||||
var/slip_in_message = pick("slides sideways in an odd way, and disappears", "jumps into an unseen dimension",\
|
||||
"sticks one leg straight out, wiggles [user.p_their()] foot, and is suddenly gone", "stops, then blinks out of reality", \
|
||||
"is pulled into an invisible vortex, vanishing from sight")
|
||||
var/slip_out_message = pick("silently fades in", "leaps out of thin air","appears", "walks out of an invisible doorway",\
|
||||
"slides out of a fold in spacetime")
|
||||
|
||||
to_chat(user, span_notice("You try to align with the bluespace stream..."))
|
||||
if(do_after(user, 20, target = src))
|
||||
var/turf/source_turf = get_turf(src)
|
||||
var/turf/destination_turf = get_turf(linked_to)
|
||||
if(!do_after(user, 2 SECONDS, target = src))
|
||||
return
|
||||
|
||||
new /obj/effect/temp_visual/bluespace_fissure(source_turf)
|
||||
new /obj/effect/temp_visual/bluespace_fissure(destination_turf)
|
||||
var/turf/source_turf = get_turf(src)
|
||||
var/turf/destination_turf = get_turf(linked_to)
|
||||
|
||||
user.visible_message(span_warning("[user] [slip_in_message]."), null, null, null, user)
|
||||
new /obj/effect/temp_visual/bluespace_fissure(source_turf)
|
||||
new /obj/effect/temp_visual/bluespace_fissure(destination_turf)
|
||||
|
||||
if(!do_teleport(user, destination_turf, no_effects = TRUE))
|
||||
user.visible_message(span_warning("[user] [slip_out_message], ending up exactly where they left."), null, null, null, user)
|
||||
return
|
||||
user.visible_message(span_warning("[user] [slip_in_message]."), ignored_mobs = user)
|
||||
|
||||
if(do_teleport(user, destination_turf, no_effects = TRUE))
|
||||
user.visible_message(span_warning("[user] [slip_out_message]."), span_notice("...and find your way to the other side."))
|
||||
else
|
||||
user.visible_message(span_warning("[user] [slip_out_message], ending up exactly where they left."), span_notice("...and find yourself where you started?"))
|
||||
|
||||
/obj/effect/hallucination/simple/bluespace_stream/attack_tk(mob/user)
|
||||
|
||||
/obj/effect/client_image_holder/bluespace_stream/attack_tk(mob/user)
|
||||
to_chat(user, span_warning("\The [src] actively rejects your mind, and the bluespace energies surrounding it disrupt your telekinesis!"))
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
@@ -353,62 +356,73 @@
|
||||
gain_text = "<span class='warning'>Justice is coming for you.</span>"
|
||||
lose_text = "<span class='notice'>You were absolved for your crimes.</span>"
|
||||
random_gain = FALSE
|
||||
var/obj/effect/hallucination/simple/securitron/beepsky
|
||||
/// A ref to our fake beepsky image that we chase the owner with
|
||||
var/obj/effect/client_image_holder/securitron/beepsky
|
||||
|
||||
/datum/brain_trauma/special/beepsky/Destroy()
|
||||
QDEL_NULL(beepsky)
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/special/beepsky/on_gain()
|
||||
create_securitron()
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/special/beepsky/proc/create_securitron()
|
||||
QDEL_NULL(beepsky)
|
||||
var/turf/where = locate(owner.x + pick(-12, 12), owner.y + pick(-12, 12), owner.z)
|
||||
beepsky = new(where, owner)
|
||||
beepsky.victim = owner
|
||||
|
||||
/datum/brain_trauma/special/beepsky/on_lose()
|
||||
QDEL_NULL(beepsky)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/special/beepsky/on_life()
|
||||
if(QDELETED(beepsky) || !beepsky.loc || beepsky.z != owner.z)
|
||||
QDEL_NULL(beepsky)
|
||||
if(prob(30))
|
||||
create_securitron()
|
||||
else
|
||||
return
|
||||
|
||||
if(get_dist(owner, beepsky) >= 10 && prob(20))
|
||||
QDEL_NULL(beepsky)
|
||||
create_securitron()
|
||||
|
||||
if(owner.stat != CONSCIOUS)
|
||||
if(prob(20))
|
||||
owner.playsound_local(beepsky, 'sound/voice/beepsky/iamthelaw.ogg', 50)
|
||||
return
|
||||
|
||||
if(get_dist(owner, beepsky) <= 1)
|
||||
owner.playsound_local(owner, 'sound/weapons/egloves.ogg', 50)
|
||||
owner.visible_message(span_warning("[owner]'s body jerks as if it was shocked."), span_userdanger("You feel the fist of the LAW."))
|
||||
owner.take_bodypart_damage(0,0,rand(40, 70))
|
||||
QDEL_NULL(beepsky)
|
||||
|
||||
if(prob(20) && get_dist(owner, beepsky) <= 8)
|
||||
owner.playsound_local(beepsky, 'sound/voice/beepsky/criminal.ogg', 40)
|
||||
..()
|
||||
|
||||
/obj/effect/hallucination/simple/securitron
|
||||
/obj/effect/client_image_holder/securitron
|
||||
name = "Securitron"
|
||||
desc = "The LAW is coming."
|
||||
image_icon = 'icons/mob/silicon/aibots.dmi'
|
||||
image_state = "secbot-c"
|
||||
var/victim
|
||||
|
||||
/obj/effect/hallucination/simple/securitron/Initialize(mapload)
|
||||
/obj/effect/client_image_holder/securitron/Initialize(mapload)
|
||||
. = ..()
|
||||
name = pick("Officer Beepsky", "Officer Johnson", "Officer Pingsky")
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/effect/hallucination/simple/securitron/process()
|
||||
if(prob(60))
|
||||
forceMove(get_step_towards(src, victim))
|
||||
if(prob(5))
|
||||
to_chat(victim, span_name("[name]</span> exclaims, \"<span class='robotic'>Level 10 infraction alert!\""))
|
||||
|
||||
/obj/effect/hallucination/simple/securitron/Destroy()
|
||||
/obj/effect/client_image_holder/securitron/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess,src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/client_image_holder/securitron/process()
|
||||
if(prob(40))
|
||||
return
|
||||
|
||||
var/mob/victim = pick(who_sees_us)
|
||||
forceMove(get_step_towards(src, victim))
|
||||
if(prob(5))
|
||||
var/beepskys_cry = "Level 10 infraction alert!"
|
||||
to_chat(victim, "<span class='name'>[name]</span> exclaims, \"<span class='robotic'>[beepskys_cry]</span>\"")
|
||||
if(victim.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
|
||||
victim.create_chat_message(src, raw_message = beepskys_cry, spans = list("robotic"))
|
||||
|
||||
@@ -61,4 +61,4 @@
|
||||
to_chat(M, span_userdanger("[pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")]"))
|
||||
else
|
||||
to_chat(M, span_notice("[pick(healthy_messages)]"))
|
||||
M.hallucination += (45 * power)
|
||||
M.adjust_hallucinations(90 SECONDS * power)
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
M.reagents.remove_reagent(/datum/reagent/toxin/mindbreaker, 5)
|
||||
if(M.reagents.has_reagent(/datum/reagent/toxin/histamine))
|
||||
M.reagents.remove_reagent(/datum/reagent/toxin/histamine, 5)
|
||||
M.hallucination = max(0, M.hallucination - 10)
|
||||
|
||||
M.adjust_hallucinations(-20 SECONDS)
|
||||
|
||||
if(A.stage >= 5)
|
||||
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -3)
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
if(DT_PROB(2.5, delta_time) && owner.stat == CONSCIOUS)
|
||||
owner.emote("scream")
|
||||
if(prob(25))
|
||||
owner.hallucination += 20
|
||||
owner.adjust_hallucinations(40 SECONDS)
|
||||
|
||||
//Dwarfism shrinks your body and lets you pass tables.
|
||||
/datum/mutation/human/dwarfism
|
||||
|
||||
@@ -468,28 +468,41 @@
|
||||
|
||||
/datum/quirk/insanity
|
||||
name = "Reality Dissociation Syndrome"
|
||||
desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. THIS IS NOT A LICENSE TO GRIEF."
|
||||
desc = "You suffer from a severe disorder that causes very vivid hallucinations. \
|
||||
Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. \
|
||||
THIS IS NOT A LICENSE TO GRIEF."
|
||||
icon = "grin-tongue-wink"
|
||||
value = -8
|
||||
mob_trait = TRAIT_INSANITY
|
||||
gain_text = "<span class='userdanger'>...</span>"
|
||||
lose_text = "<span class='notice'>You feel in tune with the world again.</span>"
|
||||
gain_text = span_userdanger("...")
|
||||
lose_text = span_notice("You feel in tune with the world again.")
|
||||
medical_record_text = "Patient suffers from acute Reality Dissociation Syndrome and experiences vivid hallucinations."
|
||||
hardcore_value = 6
|
||||
processing_quirk = TRUE
|
||||
|
||||
/datum/quirk/insanity/process(delta_time)
|
||||
if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
|
||||
/datum/quirk/insanity/add()
|
||||
if(!iscarbon(quirk_holder))
|
||||
return
|
||||
var/mob/living/carbon/carbon_quirk_holder = quirk_holder
|
||||
|
||||
if(DT_PROB(2, delta_time))
|
||||
quirk_holder.hallucination += rand(10, 25)
|
||||
// Setup our special RDS mild hallucination.
|
||||
// Not a unique subtype so not to plague subtypesof,
|
||||
// also as we inherit the names and values from our quirk.
|
||||
var/datum/brain_trauma/mild/hallucinations/added_trauma = new()
|
||||
added_trauma.resilience = TRAUMA_RESILIENCE_ABSOLUTE
|
||||
added_trauma.name = name
|
||||
added_trauma.desc = medical_record_text
|
||||
added_trauma.scan_desc = lowertext(name)
|
||||
added_trauma.gain_text = null
|
||||
added_trauma.lose_text = null
|
||||
|
||||
/datum/quirk/insanity/post_add() //I don't /think/ we'll need this but for newbies who think "roleplay as insane" = "license to kill" it's probably a good thing to have
|
||||
carbon_quirk_holder.gain_trauma(added_trauma)
|
||||
|
||||
/datum/quirk/insanity/post_add()
|
||||
if(!quirk_holder.mind || quirk_holder.mind.special_role)
|
||||
return
|
||||
to_chat(quirk_holder, "<span class='big bold info'>Please note that your dissociation syndrome does NOT give you the right to attack people or otherwise cause any interference to \
|
||||
the round. You are not an antagonist, and the rules will treat you the same as other crewmembers.</span>")
|
||||
// I don't /think/ we'll need this, but for newbies who think "roleplay as insane" = "license to kill",
|
||||
// it's probably a good thing to have.
|
||||
to_chat(quirk_holder, "<span class='big bold info'>Please note that your [lowertext(name)] does NOT give you the right to attack people or otherwise cause any interference to \
|
||||
the round. You are not an antagonist, and the rules will treat you the same as other crewmembers.</span>")
|
||||
|
||||
/datum/quirk/social_anxiety
|
||||
name = "Social Anxiety"
|
||||
|
||||
@@ -378,17 +378,30 @@
|
||||
. = ..()
|
||||
to_chat(owner, "<span class='reallybig redtext'>RIP AND TEAR</span>")
|
||||
SEND_SOUND(owner, sound('sound/hallucinations/veryfar_noise.ogg'))
|
||||
new /datum/hallucination/delusion(owner, forced = TRUE, force_kind = "demon", duration = duration, skip_nearby = FALSE)
|
||||
chainsaw = new(get_turf(owner))
|
||||
owner.log_message("entered a blood frenzy", LOG_ATTACK)
|
||||
ADD_TRAIT(chainsaw, TRAIT_NODROP, CHAINSAW_FRENZY_TRAIT)
|
||||
owner.cause_hallucination( \
|
||||
/datum/hallucination/delusion/preset/demon, \
|
||||
"[id] status effect", \
|
||||
duration = duration, \
|
||||
affects_us = FALSE, \
|
||||
affects_others = TRUE, \
|
||||
skip_nearby = FALSE, \
|
||||
play_wabbajack = FALSE, \
|
||||
)
|
||||
|
||||
owner.drop_all_held_items()
|
||||
|
||||
chainsaw = new(get_turf(owner))
|
||||
ADD_TRAIT(chainsaw, TRAIT_NODROP, CHAINSAW_FRENZY_TRAIT)
|
||||
owner.put_in_hands(chainsaw, forced = TRUE)
|
||||
chainsaw.attack_self(owner)
|
||||
owner.reagents.add_reagent(/datum/reagent/medicine/adminordrazine,25)
|
||||
|
||||
owner.log_message("entered a blood frenzy", LOG_ATTACK)
|
||||
owner.reagents.add_reagent(/datum/reagent/medicine/adminordrazine, 25)
|
||||
to_chat(owner, span_warning("KILL, KILL, KILL! YOU HAVE NO ALLIES ANYMORE, KILL THEM ALL!"))
|
||||
|
||||
var/datum/client_colour/colour = owner.add_client_colour(/datum/client_colour/bloodlust)
|
||||
QDEL_IN(colour, 1.1 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/mayhem/on_remove()
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/// Hallucination status effect. How most hallucinations end up happening.
|
||||
/// Hallucinations are drawn from the global weighted list, random_hallucination_weighted_list
|
||||
/datum/status_effect/hallucination
|
||||
id = "hallucination"
|
||||
alert_type = null
|
||||
tick_interval = 2 SECONDS
|
||||
/// Can this hallucination apply to silicons?
|
||||
var/affects_silicons = FALSE
|
||||
/// The lower range of when the next hallucination will trigger after one occurs.
|
||||
var/lower_tick_interval = 10 SECONDS
|
||||
/// The upper range of when the next hallucination will trigger after one occurs.
|
||||
var/upper_tick_interval = 60 SECONDS
|
||||
/// The cooldown for when the next hallucination can occur
|
||||
COOLDOWN_DECLARE(hallucination_cooldown)
|
||||
|
||||
/datum/status_effect/hallucination/on_creation(
|
||||
mob/living/new_owner,
|
||||
duration = 10 SECONDS,
|
||||
affects_silicons = FALSE,
|
||||
)
|
||||
|
||||
src.duration = duration
|
||||
src.affects_silicons = affects_silicons
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/hallucination/on_apply()
|
||||
if(!affects_silicons && issilicon(owner))
|
||||
return FALSE
|
||||
|
||||
RegisterSignal(owner, COMSIG_LIVING_POST_FULLY_HEAL, .proc/remove_hallucinations)
|
||||
RegisterSignal(owner, COMSIG_LIVING_HEALTHSCAN, .proc/on_health_scan)
|
||||
if(iscarbon(owner))
|
||||
RegisterSignal(owner, COMSIG_CARBON_CHECKING_BODYPART, .proc/on_check_bodypart)
|
||||
RegisterSignal(owner, COMSIG_CARBON_BUMPED_AIRLOCK_OPEN, .proc/on_bump_airlock)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/hallucination/on_remove()
|
||||
UnregisterSignal(owner, list(
|
||||
COMSIG_LIVING_POST_FULLY_HEAL,
|
||||
COMSIG_LIVING_HEALTHSCAN,
|
||||
COMSIG_CARBON_CHECKING_BODYPART,
|
||||
COMSIG_CARBON_BUMPED_AIRLOCK_OPEN,
|
||||
))
|
||||
|
||||
/// Signal proc for [COMSIG_LIVING_POST_FULLY_HEAL], terminate on full heal
|
||||
/datum/status_effect/hallucination/proc/remove_hallucinations(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
qdel(src)
|
||||
|
||||
/// Signal proc for [COMSIG_LIVING_HEALTHSCAN]. Show we're hallucinating to (advanced) scanners.
|
||||
/datum/status_effect/hallucination/proc/on_health_scan(datum/source, list/render_list, advanced, mob/user, mode)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!advanced)
|
||||
return
|
||||
|
||||
render_list += "<span class='info ml-1'>Subject is hallucinating.</span>\n"
|
||||
|
||||
/// Signal proc for [COMSIG_CARBON_CHECKING_BODYPART],
|
||||
/// checking bodyparts while hallucinating can cause them to appear more damaged than they are
|
||||
/datum/status_effect/hallucination/proc/on_check_bodypart(mob/living/carbon/source, obj/item/bodypart/examined, list/check_list, list/limb_damage)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(prob(30))
|
||||
limb_damage[BRUTE] += rand(30, 40)
|
||||
if(prob(30))
|
||||
limb_damage[BURN] += rand(30, 40)
|
||||
|
||||
/// Signal proc for [COMSIG_CARBON_BUMPED_AIRLOCK_OPEN], bumping an airlock can cause a fake zap.
|
||||
/// This only happens on airlock bump, future TODO - make this chance roll for attack_hand opening airlocks too
|
||||
/datum/status_effect/hallucination/proc/on_bump_airlock(mob/living/carbon/source, obj/machinery/door/airlock/bumped)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
// 1% chance to fake a shock.
|
||||
if(prob(99) || !source.should_electrocute() || bumped.operating)
|
||||
return
|
||||
|
||||
source.cause_hallucination(/datum/hallucination/shock, "hallucinated shock from [bumped]",)
|
||||
return STOP_BUMP
|
||||
|
||||
/datum/status_effect/hallucination/tick(delta_time, times_fired)
|
||||
if(owner.stat == DEAD)
|
||||
return
|
||||
if(!COOLDOWN_FINISHED(src, hallucination_cooldown))
|
||||
return
|
||||
|
||||
var/datum/hallucination/picked_hallucination = pick_weight(GLOB.random_hallucination_weighted_list)
|
||||
owner.cause_hallucination(picked_hallucination, "[id] status effect")
|
||||
COOLDOWN_START(src, hallucination_cooldown, rand(lower_tick_interval, upper_tick_interval))
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Screwy hud status.
|
||||
*
|
||||
* Applied to carbons, it will make their health bar look like it's incorrect -
|
||||
* in crit (SCREWYHUD_CRIT), dead (SCREWYHUD_DEAD), or fully healthy (SCREWYHUD_HEALTHY)
|
||||
*
|
||||
* Grouped status effect, so multiple sources can add a screwyhud without
|
||||
* accidentally removing another source's hud.
|
||||
*/
|
||||
/datum/status_effect/grouped/screwy_hud
|
||||
alert_type = null
|
||||
/// The priority of this screwyhud over other screwyhuds.
|
||||
var/priority = -1
|
||||
/// The icon we override our owner's healths.icon_state with
|
||||
var/override_icon
|
||||
|
||||
/datum/status_effect/grouped/screwy_hud/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
|
||||
RegisterSignal(owner, COMSIG_CARBON_UPDATING_HEALTH_HUD, .proc/on_health_hud_updated)
|
||||
owner.update_health_hud()
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/grouped/screwy_hud/on_remove()
|
||||
UnregisterSignal(owner, COMSIG_CARBON_UPDATING_HEALTH_HUD)
|
||||
owner.update_health_hud()
|
||||
|
||||
/datum/status_effect/grouped/screwy_hud/proc/on_health_hud_updated(mob/living/carbon/source, shown_health_amount)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
// Shouldn't even be running if we're dead, but just in case...
|
||||
if(source.stat == DEAD)
|
||||
return
|
||||
|
||||
// It's entirely possible we have multiple screwy huds on one mob.
|
||||
// Defer to priority to determine which to show. If our's is lower, don't show it.
|
||||
for(var/datum/status_effect/grouped/screwy_hud/other_screwy_hud in source.status_effects)
|
||||
if(other_screwy_hud.priority > priority)
|
||||
return
|
||||
|
||||
source.hud_used.healths.icon_state = override_icon
|
||||
return COMPONENT_OVERRIDE_HEALTH_HUD
|
||||
|
||||
/datum/status_effect/grouped/screwy_hud/fake_dead
|
||||
id = "fake_hud_dead"
|
||||
priority = 100 // death is absolute
|
||||
override_icon = "health7"
|
||||
|
||||
/datum/status_effect/grouped/screwy_hud/fake_crit
|
||||
id = "fake_hud_crit"
|
||||
priority = 90 // crit is almost death, and death is absolute
|
||||
override_icon = "health6"
|
||||
|
||||
/datum/status_effect/grouped/screwy_hud/fake_healthy
|
||||
id = "fake_hud_healthy"
|
||||
priority = 10 // fully healthy is the opposite of death, which is absolute
|
||||
override_icon = "health0"
|
||||
@@ -161,8 +161,15 @@ GLOBAL_LIST_INIT(voice_of_god_commands, init_voice_of_god_commands())
|
||||
trigger = "see\\s*the\\s*truth|hallucinate"
|
||||
|
||||
/datum/voice_of_god_command/hallucinate/execute(list/listeners, mob/living/user, power_multiplier = 1, message)
|
||||
for(var/mob/living/carbon/target in listeners)
|
||||
new /datum/hallucination/delusion(target, TRUE, null, 150 * power_multiplier, 0)
|
||||
for(var/mob/living/target in listeners)
|
||||
target.cause_hallucination( \
|
||||
get_random_valid_hallucination_subtype(/datum/hallucination/delusion/preset), \
|
||||
"voice of god", \
|
||||
duration = 15 SECONDS * power_multiplier, \
|
||||
affects_us = FALSE, \
|
||||
affects_others = TRUE, \
|
||||
skip_nearby = FALSE, \
|
||||
)
|
||||
|
||||
/// This command wakes up the listeners.
|
||||
/datum/voice_of_god_command/wake_up
|
||||
|
||||
Reference in New Issue
Block a user