Hallucinations Overhaul (#8259)

This commit is contained in:
Doxxmedearly
2020-03-20 22:24:06 +02:00
committed by GitHub
parent 4ebdbdafdc
commit 938deeb66a
20 changed files with 1353 additions and 421 deletions
+7 -1
View File
@@ -176,6 +176,7 @@
#include "code\controllers\subsystems\garbage.dm"
#include "code\controllers\subsystems\ghostroles.dm"
#include "code\controllers\subsystems\global_listener.dm"
#include "code\controllers\subsystems\hallucinations.dm"
#include "code\controllers\subsystems\http.dm"
#include "code\controllers\subsystems\icon_cache.dm"
#include "code\controllers\subsystems\icon_smooth.dm"
@@ -1532,7 +1533,6 @@
#include "code\modules\examine\descriptions\weapons.dm"
#include "code\modules\ext_scripts\python.dm"
#include "code\modules\flufftext\Dreaming.dm"
#include "code\modules\flufftext\Hallucination.dm"
#include "code\modules\flufftext\TextFilters.dm"
#include "code\modules\food\recipe.dm"
#include "code\modules\food\recipes_fryer.dm"
@@ -1569,6 +1569,12 @@
#include "code\modules\ghosttrap\trap.dm"
#include "code\modules\global_listener\devices.dm"
#include "code\modules\global_listener\interfaces.dm"
#include "code\modules\hallucinations\hallucinations.dm"
#include "code\modules\hallucinations\mob.dm"
#include "code\modules\hallucinations\types\basic.dm"
#include "code\modules\hallucinations\types\mirage.dm"
#include "code\modules\hallucinations\types\powers.dm"
#include "code\modules\hallucinations\types\sound.dm"
#include "code\modules\heavy_vehicle\_mech_setup.dm"
#include "code\modules\heavy_vehicle\mech_construction.dm"
#include "code\modules\heavy_vehicle\mech_damage.dm"
+2
View File
@@ -7,7 +7,9 @@
#define SPAN_DANGER(X) "<span class='danger'>[X]</span>"
#define SPAN_CULT(X) "<span class='cult'>[X]</span>"
#define SPAN_GOOD(X) "<span class='good'>[X]</span>"
#define SPAN_BAD(X) "<span class='bad'>[X]</span>"
#define SPAN_ALIEN(X) "<span class='alium'>[X]</span>"
#define SPAN_ALERT(X) "<span class='alert'>[X]</span>"
#define SPAN_ITALIC(X) "<span class='italic'>[X]</span>"
#define SPAN_BOLD(X) "<span class='bold'>[X]</span>"
#define SPAN_SUBTLE(X) "<span class='subtle'>[X]</span>"
@@ -0,0 +1,36 @@
/var/datum/controller/subsystem/hallucinations/SShallucinations
/datum/controller/subsystem/hallucinations
name = "Hallucinations"
flags = SS_NO_FIRE
var/list/hallucinated_phrases = list()
var/list/hallucinated_actions = list()
var/list/hallucinated_thoughts = list()
var/static/list/hal_emote = list("mutters quietly.", "stares.", "grunts.", "looks around.", "twitches.", "shivers.", "swats at the air.", "wobbles.", "gasps!", "blinks rapidly.", "murmurs.",
"dry heaves!", "twitches violently.", "giggles.", "drools.", "scratches all over.", "grinds their teeth.", "whispers something quietly.")
var/static/list/message_sender = list("Mom", "Dad", "Captain", "Captain(as Captain)", "help", "Home", "MaxBet Online Casino", "IDrist Corp", "Dr. Maxman",
"www.wetskrell.nt", "You are our lucky grand prize winner!", "Officer Beepsky", "Ginny", "Ian",
"what have you DONE?", "Miranda Trasen", "Central Command", "AI", "maintenance drone", "Unknown", "I don't want to die")
var/list/all_hallucinations = list()
/datum/controller/subsystem/hallucinations/New()
NEW_SS_GLOBAL(SShallucinations)
/datum/controller/subsystem/hallucinations/Initialize()
. = ..()
for(var/T in subtypesof(/datum/hallucination/))
all_hallucinations += T
hallucinated_phrases = file2list("code/modules/hallucinations/text_lists/hallucinated_phrases.txt")
hallucinated_actions = file2list("code/modules/hallucinations/text_lists/hallucinated_actions.txt") //important note when adding to this file: "you" will always be replaced by the hallucinator's name
hallucinated_thoughts = file2list("code/modules/hallucinations/text_lists/hallucinated_thoughts.txt")
/datum/controller/subsystem/hallucinations/proc/get_hallucination(var/mob/living/carbon/C)
var/list/candidates = list()
for(var/T in all_hallucinations)
var/datum/hallucination/H = new T
if(H.can_affect(C))
candidates += H
if(candidates.len)
var/datum/hallucination/D = pick(candidates)
return D
-5
View File
@@ -472,11 +472,6 @@ About the new airlock wires panel:
return
else /*if(src.justzap)*/
return
else if(user.hallucination > 50 && prob(10) && src.operating == 0 && !user.is_diona() && !user.isSynthetic())
to_chat(user, span("danger", "You feel a powerful shock course through your body!"))
user.adjustHalLoss(10)
user.stunned += 10
return
..(user)
/obj/machinery/door/airlock/proc/isElectrified()
@@ -1116,6 +1116,12 @@ var/global/list/obj/item/device/pda/PDAs = list()
t = sanitize(t)
//t = readd_quotes(t)
t = replace_characters(t, list("&#34;" = "\""))
if(iscarbon(U) && t)
var/mob/living/carbon/C = U
if(C.hallucination >= 50 && prob(C.hallucination / 10)) //If you're really hallucinating, you might not be typing what you think you are
var/t_orig = t
t = pick(SShallucinations.hallucinated_phrases) //see carbon/hallucination.dm
log_pda("[usr] (PDA: [C.name]) typed \"[t_orig]\" then hallucination changed it to \"[t]\". Recipient was [P.owner]",ckey=key_name(C),ckey_target=key_name(P.owner))
if (!t || !istype(P))
return
if (!in_range(src, U) && loc != U)
+2 -1
View File
@@ -24,7 +24,7 @@
#define UNDERWATER 22
#define DRUGGED 23
#define DIZZY 24
#define PSYCHOTIC 25
#define STANDARD_STATION STONEROOM
#define LARGE_ENCLOSED HANGAR
@@ -35,6 +35,7 @@
#define SMALL_SOFTFLOOR ROOM
#define ASTEROID CAVE
#define SPACE UNDERWATER
#define PSYCHOTIC PARKING_LOT
//footsteps
var/list/blank_footstep = list('sound/effects/footstep/blank.ogg')
-392
View File
@@ -1,392 +0,0 @@
/*
Ideas for the subtle effects of hallucination:
Light up oxygen/phoron indicators (done)
Cause health to look critical/dead, even when standing (done)
Characters silently watching you
Brief flashes of fire/space/bombs/c4/dangerous shit (done)
Items that are rare/traitorous/don't exist appearing in your inventory slots (done)
Strange audio (should be rare) (done)
Gunshots/explosions/opening doors/less rare audio (done)
*/
mob/living/carbon/var
image/halimage
image/halbody
obj/halitem
hal_screwyhud = 0 //1 - critical, 2 - dead, 3 - oxygen indicator, 4 - toxin indicator
handling_hal = 0
hal_crit = 0
mob/living/carbon/proc/handle_hallucinations()
if(handling_hal) return
handling_hal = 1
while(client && hallucination > 20)
sleep(rand(200,500)/(hallucination/25))
var/halpick = rand(1,100)
switch(halpick)
if(0 to 15)
//Screwy HUD
hal_screwyhud = pick(1,2,3,3,4,4)
spawn(rand(100,250))
hal_screwyhud = 0
if(16 to 25)
//Strange items
if(!halitem)
halitem = new
var/list/slots_free = list(ui_lhand,ui_rhand)
if(l_hand) slots_free -= ui_lhand
if(r_hand) slots_free -= ui_rhand
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/H = src
if(!H.belt) slots_free += ui_belt
if(!H.l_store) slots_free += ui_storage1
if(!H.r_store) slots_free += ui_storage2
if(slots_free.len)
halitem.screen_loc = pick(slots_free)
halitem.layer = 50
switch(rand(1,6))
if(1) //revolver
halitem.icon = 'icons/obj/guns/revolver.dmi'
halitem.icon_state = "revolver"
halitem.name = "Revolver"
if(2) //c4
halitem.icon = 'icons/obj/assemblies.dmi'
halitem.icon_state = "plastic-explosive0"
halitem.name = "Mysterious Package"
if(prob(25))
halitem.icon_state = "c4small_1"
if(3) //sword
halitem.icon = 'icons/obj/weapons.dmi'
halitem.icon_state = "sword1"
halitem.name = "Sword"
if(4) //stun baton
halitem.icon = 'icons/obj/weapons.dmi'
halitem.icon_state = "stunbaton"
halitem.name = "Stun Baton"
if(5) //emag
halitem.icon = 'icons/obj/card.dmi'
halitem.icon_state = "emag"
halitem.name = "Cryptographic Sequencer"
if(6) //flashbang
halitem.icon = 'icons/obj/grenade.dmi'
halitem.icon_state = "flashbang1"
halitem.name = "Flashbang"
if(client) client.screen += halitem
spawn(rand(100,250))
if(client)
client.screen -= halitem
halitem = null
if(26 to 40)
//Flashes of danger
if(!halimage)
var/list/possible_points = list()
for(var/turf/simulated/floor/F in view(src,world.view))
possible_points += F
if(possible_points.len)
var/turf/simulated/floor/target = pick(possible_points)
switch(rand(1,3))
if(1)
halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
if(2)
halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
if(3)
halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
if(client) client.images += halimage
spawn(rand(10,50)) //Only seen for a brief moment.
if(client) client.images -= halimage
halimage = null
if(41 to 65)
//Strange audio
switch(rand(1,12))
if(1) sound_to(src, 'sound/machines/airlock.ogg')
if(2)
if(prob(50)) sound_to(src, 'sound/effects/Explosion1.ogg')
else sound_to(src, 'sound/effects/Explosion2.ogg')
if(3) sound_to(src, 'sound/effects/explosionfar.ogg')
if(4) sound_to(src, 'sound/effects/glass_break1.ogg')
if(5) sound_to(src, 'sound/effects/glass_break2.ogg')
if(6) sound_to(src, 'sound/effects/glass_break3.ogg')
if(7) sound_to(src, 'sound/machines/twobeep.ogg')
if(8) sound_to(src, 'sound/machines/windowdoor.ogg')
if(9)
//To make it more realistic, I added two gunshots (enough to kill)
sound_to(src, 'sound/weapons/gunshot/gunshot1.ogg')
spawn(rand(10,30))
sound_to(src, 'sound/weapons/gunshot/gunshot1.ogg')
if(10) sound_to(src, 'sound/weapons/smash.ogg')
if(11)
//Same as above, but with tasers.
sound_to(src, 'sound/weapons/Taser.ogg')
spawn(rand(10,30))
sound_to(src, 'sound/weapons/Taser.ogg')
//Rare audio
if(12)
//These sounds are (mostly) taken from Hidden: Source
var/list/creepyasssounds = list(
'sound/effects/ghost.ogg',
'sound/effects/ghost2.ogg',
'sound/effects/Heart Beat.ogg',
'sound/effects/screech.ogg',
'sound/hallucinations/behind_you1.ogg',
'sound/hallucinations/behind_you2.ogg',
'sound/hallucinations/far_noise.ogg',
'sound/hallucinations/growl1.ogg',
'sound/hallucinations/growl2.ogg',
'sound/hallucinations/growl3.ogg',
'sound/hallucinations/im_here1.ogg',
'sound/hallucinations/im_here2.ogg',
'sound/hallucinations/i_see_you1.ogg',
'sound/hallucinations/i_see_you2.ogg',
'sound/hallucinations/look_up1.ogg',
'sound/hallucinations/look_up2.ogg',
'sound/hallucinations/over_here1.ogg',
'sound/hallucinations/over_here2.ogg',
'sound/hallucinations/over_here3.ogg',
'sound/hallucinations/turn_around1.ogg',
'sound/hallucinations/turn_around2.ogg',
'sound/hallucinations/veryfar_noise.ogg',
'sound/hallucinations/wail.ogg')
sound_to(src, pick(creepyasssounds))
if(66 to 70)
//Flashes of danger
if(!halbody)
var/list/possible_points = list()
for(var/turf/simulated/floor/F in view(src,world.view))
possible_points += F
if(possible_points.len)
var/turf/simulated/floor/target = pick(possible_points)
switch(rand(1,4))
if(1)
halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER)
if(2,3)
halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
if(4)
halbody = image('icons/mob/npc/alien.dmi',target,"alienother",TURF_LAYER)
// if(5)
// halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER)
if(client) client.images += halbody
spawn(rand(50,80)) //Only seen for a brief moment.
if(client) client.images -= halbody
halbody = null
if(71 to 72)
//Fake death
// src.sleeping_willingly = 1
src.sleeping = 20
hal_crit = 1
hal_screwyhud = 1
spawn(rand(50,100))
// src.sleeping_willingly = 0
src.sleeping = 0
hal_crit = 0
hal_screwyhud = 0
handling_hal = 0
/*obj/machinery/proc/mockpanel(list/buttons,start_txt,end_txt,list/mid_txts)
if(!mocktxt)
mocktxt = ""
var/possible_txt = list("Launch Escape Pods","Self-Destruct Sequence","\[Swipe ID\]","De-Monkify",\
"Reticulate Splines","Plasma","Open Valve","Lockdown","Nerf Airflow","Kill Traitor","Nihilism",\
"OBJECTION!","Arrest Stephen Bowman","Engage Anti-Trenna Defenses","Increase Captain IQ","Retrieve Arms",\
"Play Charades","Oxygen","Inject BeAcOs","Ninja Lizards","Limit Break","Build Sentry")
if(mid_txts)
while(mid_txts.len)
var/mid_txt = pick(mid_txts)
mocktxt += mid_txt
mid_txts -= mid_txt
while(buttons.len)
var/button = pick(buttons)
var/button_txt = pick(possible_txt)
mocktxt += "<a href='?src=\ref[src];[button]'>[button_txt]</a><br>"
buttons -= button
possible_txt -= button_txt
return start_txt + mocktxt + end_txt + "</TT></BODY></HTML>"
proc/check_panel(mob/M)
if (istype(M, /mob/living/carbon/human) || istype(M, /mob/living/silicon/ai))
if(M.hallucination < 15)
return 1
return 0*/
/obj/effect/fake_attacker
icon = null
icon_state = null
name = ""
desc = ""
density = 0
anchored = 1
opacity = 0
var/mob/living/carbon/human/my_target = null
var/weapon_name = null
var/obj/item/weap = null
var/image/stand_icon = null
var/image/currentimage = null
var/icon/base = null
var/s_tone
var/mob/living/clone = null
var/image/left
var/image/right
var/image/up
var/collapse
var/image/down
var/health = 100
attackby(var/obj/item/P as obj, mob/user as mob)
step_away(src,my_target,2)
for(var/mob/M in oviewers(world.view,my_target))
to_chat(M, "<span class='danger'>[my_target] flails around wildly.</span>")
my_target.show_message("<span class='danger'>[src] has been attacked by [my_target] </span>", 1) //Lazy.
src.health -= P.force
return
Crossed(var/mob/M, somenumber)
if(M == my_target)
step_away(src,my_target,2)
if(prob(30))
for(var/mob/O in oviewers(world.view , my_target))
to_chat(O, "<span class='danger'>[my_target] stumbles around.</span>")
New()
..()
addtimer(CALLBACK(src, .proc/end), 300)
step_away(src,my_target,2)
spawn attack_loop()
proc/end()
if (my_target)
my_target.hallucinations -= src
walk(src, 0)
qdel(src)
proc/updateimage()
if(src.dir == NORTH)
del currentimage // Can't qdel images.
src.currentimage = new /image(up,src)
else if(src.dir == SOUTH)
del currentimage
src.currentimage = new /image(down,src)
else if(src.dir == EAST)
del currentimage
src.currentimage = new /image(right,src)
else if(src.dir == WEST)
del currentimage
src.currentimage = new /image(left,src)
my_target << currentimage
proc/attack_loop()
while(!QDELETED(src))
sleep(rand(5,10))
if(src.health < 0)
collapse()
continue
if(get_dist(src,my_target) > 1)
src.set_dir(get_dir(src,my_target))
step_towards(src,my_target)
updateimage()
else
if(prob(15))
if(weapon_name)
my_target << sound(pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg'))
my_target.show_message("<span class='danger'>[my_target] has been attacked with [weapon_name] by [src.name] </span>", 1)
my_target.adjustHalLoss(10)
if(prob(20)) my_target.eye_blurry += 3
if(prob(33))
if(!locate(/obj/effect/overlay) in my_target.loc)
fake_blood(my_target)
else
my_target << sound(pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'))
my_target.show_message("<span class='danger'>[src.name] has punched [my_target]!</span>", 1)
my_target.adjustHalLoss(10)
if(prob(33))
if(!locate(/obj/effect/overlay) in my_target.loc)
fake_blood(my_target)
if(prob(15))
step_away(src,my_target,2)
proc/collapse()
collapse = 1
updateimage()
/proc/fake_blood(var/mob/target)
var/obj/effect/overlay/O = new/obj/effect/overlay(target.loc)
O.name = "blood"
var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1)
target << I
QDEL_IN(O, 300)
var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_magazine/a357,\
/obj/item/gun/energy/crossbow, /obj/item/melee/energy/sword,\
/obj/item/storage/box/syndicate, /obj/item/storage/box/emps,\
/obj/item/cartridge/syndicate, /obj/item/clothing/under/chameleon,\
/obj/item/clothing/shoes/syndigaloshes, /obj/item/card/id/syndicate,\
/obj/item/clothing/mask/gas/voice, /obj/item/clothing/glasses/thermal,\
/obj/item/device/chameleon, /obj/item/card/emag,\
/obj/item/storage/toolbox/syndicate, /obj/item/aiModule,\
/obj/item/device/radio/headset/syndicate, /obj/item/plastique,\
/obj/item/device/powersink, /obj/item/storage/box/syndie_kit,\
/obj/item/toy/syndicateballoon, /obj/item/gun/energy/captain,\
/obj/item/hand_tele, /obj/item/rfd/construction, /obj/item/tank/jetpack,\
/obj/item/clothing/under/rank/captain, /obj/item/aicard,\
/obj/item/clothing/shoes/magboots, /obj/item/blueprints, /obj/item/disk/nuclear,\
/obj/item/clothing/suit/space/void, /obj/item/tank)
/proc/fake_attack(var/mob/living/target)
var/mob/living/carbon/human/clone = null
var/clone_weapon = null
for(var/mob/living/carbon/human/H in living_mob_list)
if(H.stat || H.lying) continue
clone = H
break //changed the code a bit. Less randomised, but less work to do. Should be ok, world.contents aren't stored in any particular order.
if(!clone) return
//var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(outside_range(target))
var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(target.loc)
if(clone.l_hand)
if(!(locate(clone.l_hand) in non_fakeattack_weapons))
clone_weapon = clone.l_hand.name
F.weap = clone.l_hand
else if (clone.r_hand)
if(!(locate(clone.r_hand) in non_fakeattack_weapons))
clone_weapon = clone.r_hand.name
F.weap = clone.r_hand
F.name = clone.name
F.my_target = target
F.weapon_name = clone_weapon
target.hallucinations += F
F.left = image(clone,dir = WEST)
F.right = image(clone,dir = EAST)
F.up = image(clone,dir = NORTH)
F.down = image(clone,dir = SOUTH)
F.updateimage()
@@ -0,0 +1,61 @@
#define NO_THOUGHT 1 //Hallucinated thoughts will not occur on this hallucination's end()
#define NO_EMOTE 2 //User will not emote to others when this hallucination ends
#define HEARING_DEPENDENT 3 //deaf characters will not experience this hallucination
//Power Defines
#define HAL_POWER_LOW 30
#define HAL_POWER_MED 50
#define HAL_POWER_HIGH 70
/datum/hallucination
var/mob/living/carbon/holder //Who is hallucinating?
var/allow_duplicates = TRUE //This is set to false for hallucinations with long durations or ones we do not want repeated for a time
var/duration = 10 //how long before we call end()
var/min_power = 0 //mobs only get this hallucination at this threshold
var/max_power = INFINITY //mobs don't get this hallucination if it's above this threshold. Used to weed out more common ones if you're super fucked up
var/special_flags //Any special flags, defined above
/datum/hallucination/proc/start()
/datum/hallucination/proc/end()
if(holder)
if(!(special_flags & NO_THOUGHT))
holder.hallucination_thought()
if(!(special_flags & NO_EMOTE))
hallucination_emote(holder) //Always a chance to involuntarily emote to others as if on drugs
holder.hallucinations -= src
qdel(src)
//Used to verify if a hallucination can be added to the list of candidates
/datum/hallucination/proc/can_affect(mob/living/carbon/C)
if(!C.client)
return FALSE
if(!allow_duplicates && (locate(type) in C.hallucinations))
return FALSE
if(min_power > C.hallucination || max_power < C.hallucination)
return FALSE
if((special_flags & HEARING_DEPENDENT) && (C.disabilities & DEAF))
return FALSE
return TRUE
/datum/hallucination/Destroy()
holder = null
return ..()
//The actual kickoff to each effect
/datum/hallucination/proc/activate()
if(!holder || !holder.client)
return
holder.hallucinations += src
start()
addtimer(CALLBACK(src, .proc/end), duration)
//You emoting to others involuntarily. This happens mostly in end()
/datum/hallucination/proc/hallucination_emote()
if(prob(min(holder.hallucination - 5, 80)) && !holder.stat)
var/chosen_emote = pick(SShallucinations.hal_emote)
if(prob(10)) //You are aware of it in this instance
holder.visible_message("<B>[holder]</B> [chosen_emote]")
else
for(var/mob/M in oviewers(world.view, holder)) //Only shows to others, not you; you're not aware of what you're doing. Could prompt others to ask if you're okay, and lead to confusion.
to_chat(M, "<B>[holder]</B> [chosen_emote]")
+48
View File
@@ -0,0 +1,48 @@
/mob/living/carbon
var/next_hallucination = 0 //Hallucination spam limit var
var/list/hallucinations = list() //Hallucinations currently affecting the mob. Not to be confused with singular "hallucination" which is a NUM variable like confused/drowsy/eye_blind etc
//Hallucinated Hearing
/mob/living/carbon/hear_say(var/message, var/verb = "says", var/datum/language/language, var/alt_name = "",var/italics = 0, var/mob/speaker, var/sound/speech_sound, var/sound_vol)
if(hallucination >= 60 && prob(1))
var/orig_message = message
message = pick(SShallucinations.hallucinated_phrases)
log_say("Hallucination level changed [orig_message] by [speaker] to [message] for [key_name(src)].", ckey=key_name(src))
..()
/mob/living/carbon/hear_radio(var/message, var/verb="says", var/datum/language/language, var/part_a, var/part_b, var/mob/speaker, var/hard_to_hear = 0, var/vname ="")
if(hallucination >= 60 && prob(1))
var/orig_message = message
message = pick(SShallucinations.hallucinated_phrases)
log_say("Hallucination level changed [orig_message] by [speaker] to [message] for [key_name(src)].", ckey=key_name(src))
..()
//Main handling proc, called in life()
/mob/living/carbon/proc/handle_hallucinations()
hallucination -= 1 //Tick down the duration
if(!hallucination) //We're done
return
if(!client || stat || world.time < next_hallucination)
return
var/hall_delay = rand(180,250) //Time between hallucinations, modified by switch below.
switch(hallucination) //26-149 are intentionally left off, as they do not modify the delay. This is a pretty common range for hallucinations.
if(1 to 25) //Winding down, less frequent.
hall_delay *= 2
if(150 to 399) //Yo mind really fucked, more frequent.
hall_delay *= 0.75
if(400 to INFINITY) //This should only be possible in cult conversions. Very low delay to represent your flayed mind.
hall_delay *= 0.25
next_hallucination = world.time + hall_delay
var/datum/hallucination/H = SShallucinations.get_hallucination(src)
H.holder = src
H.activate()
//This is called on every end() so usually occurs a few times. Grants a thought to the user from thoughts list.
/mob/living/carbon/proc/hallucination_thought()
if(prob(min(hallucination/2, 50)))
addtimer(CALLBACK(src, .proc/hal_thought_give), rand(30,90))
/mob/living/carbon/proc/hal_thought_give()
to_chat(src, "<I>[pick(SShallucinations.hallucinated_thoughts)]</I>")
@@ -0,0 +1,56 @@
grins widely at you.
mumbles something while looking away from you.
screams!
suddenly clutches at their chest!
stumbles.
laughs!
watches you, unblinking.
twitches.
holds up a very familiar key...
cowers from you.
bleeds profusely from their eyes!
drools.
flails about, unable to breathe!
grows a fabulous head of hair!
snorts!
waves at you to come closer.
hums your favorite song.
doesn't seem to cast a shadow.
beeps.
is going to die if they don't get help!
yawns.
points a gun at you!
whispers into their headset while watching you.
frowns at you.
shakes their head at you.
looks around.
swats at the air!
coughs up a tooth.
shivers.
looks behind you.
spits blood.
shrieks!
applies some lipstick.
scowls.
looks at you and frowns.
wipes the blood from their hands.
sneezes.
screams as a loud snapping sound comes from their body!
snaps.
holds up a bloodied organ and examines it.
giggles.
looks at you and clenches a fist.
jabs a finger at you!
stomps their feet.
seems to phase out for a moment.
coughs up a plume of colorful smoke.
huffs.
licks their eyeball.
unhinges their jaw for a moment.
gives you an incredulous look.
backs away from you.
quickly shoves a knife into their pocket.
quickly holsters a gun.
blinks rapidly.
slams their hands together!
closely watches you.
@@ -0,0 +1,99 @@
Give it back!
Don't worry, we'll never be apart.
Just let me help you.
You don't know anything!
I forgive you.
Don't you remember me?
You can't keep doing this!
Help!
Are you okay?
You need to see a doctor!
Wait, who are you?
Wait, who were you?
Are you ready?
Remember our song?
Did you hear that?
Why are we here?
Let's get going!
Just go away!
It's okay, I'm here.
Where are we going?
Oh, did you forget?
You forgot about me already, didn't you?
You're not safe here.
Why are you asking me?
Don't you know any better?
It's you or me.
I can't lose you again.
You're bleeding!
You're hurt!
They're looking for you.
How are you?
Shut up for once.
Will you join me?
Didn't you call for me?
I know you lied to me.
You just had to ruin everything, didn't you?
It's so nice to see you!
Did you remember your assignment?
Don't give up!
Nobody else believes in you, but I do.
When's the shuttle coming?
The shuttle will be here in a minute.
I tried calling you last night. You never answer.
What is THAT supposed to be?
Did you hear about the fire?
I heard the news; I'm so sorry.
I didn't mean it!
What happened to your face?!
Apparently someone died.
Remember me from high-school? Well I have this great business deal proposition...
Bored?
Once you are a player with MaxBet, you will also receive lucrative weekly and monthly promotions.
Find your secret skrell crush.
Is your sexlife growing dull? Your late-night sessions growing short? Have you considered Unathi testicle transplants? Greater stamina, greater virility, greater fun.
We know who you are. Expect us.
Discovery of this ONE Vaurca pheremone has led to years of genital growth progress!
This staff assistant is making mad credits and basically, you're fucking stupid.
You have a secret admirer!
Where's your ID?
You know nobody wants you here, right?
Uh, do you know you're bleeding?
I know your secret, you know. You're bad at hiding it.
I would kill you if I could get away with it.
You should probably leave, trust me.
You'd better wake up before you forget how to.
You cannot kill me in a way that matters.
Life is too short for regrets.
There's an interesting rumor about you.
I heard what you did before you worked here.
You're disgusting.
I know you're a liar.
Your beliefs are ridiculous.
Fuck off, you nuisance.
Coming here was a mistake and you know it.
I wonder how much you'll scream?
So, you're spreading rumors about me?
Let's dance!
I know how you die. Do you want to?
I wonder how loud you'll scream.
Come on, let's get out of here.
You know I like you, right?
Why don't you just admit it?
Cry about it.
I can't believe you actually did it.
You can trust me.
I'd never betray you.
I'm excited for you to join us.
I come from the future to give warning!
Hum that song I like, please?
Just give me a hug. I need it.
Can you tell me I'm doing okay?
Isn't this all stupid?
Don't tell anyone I told you this, but...
They'll never accept you.
Someone told me they had a crush on you but were too shy to say it.
Well, you fucked it up. Again.
Let's die together.
I'm not feeling too hot.
I feel like you're the only one I can trust.
@@ -0,0 +1,57 @@
Wait, what was that?
Something is crawling on you!
Is any of this real?
You can't catch your breath!
Something's watching you...
You feel unsteady!
You're sure you've never been to this place before...
You can't feel your skin!
What just brushed your shoulder?
You hear someone whispering to you. It sounds so familiar.
When are you getting that drink you ordered?
Wait, where did your child go? What did they look like again..? You have one, right?
Crap, that assignment is due today!
When did you die, again? It's hard to remember...
You'll die if it gets any warmer!
Weren't you getting married today?
Why is it so cold here?
You need to get away from here, it's not safe!
Who are all these people?
You feel exhausted!
You're so thirsty!
Where did you put your jacket?
Finally, you can see again!
Your face feels soft.
When was your funeral supposed to be?
This place has changed...
Why is it so. Damn. Loud?!
Oh no...
You feel itchy all over!
Someone's behind you!
Where did your gun go?
You feel like you're getting sick.
Your blood feels weird.
Someone here was trying to kill you, you just know it!
Wait, this isn't your ID.
Are those footsteps?
Was that a gunshot?
Something's buzzing in your ear.
Wait, what were you doing?
You hear a constant dripping sound.
Your skin feels wet.
You feel a sudden chill.
All your problems seem to melt away.
Your head feels foggy.
The people around you really are great, aren't they?
You feel homesick.
Why does it smell like rust?
Wait, is that blood on the floor?
You feel particularly charitable.
Did you always have this many fingers?
When's the last time you ate?
Oh shit, these aren't your clothes!
You have to leave. Right now.
You suddenly feel antsy.
You can't seem to focus on anything except your problems.
Everything seems so overwhelming.
How do you wake up?
+493
View File
@@ -0,0 +1,493 @@
/datum/hallucination/announcement //fake AI announcements, complete with sound. Text is weirder than normal, but easy to glaze over.
min_power = HAL_POWER_LOW
duration = 1200 //this duration length + not allowing duplicates prevents spamming announcements on every valid handle_hallucination() which can get VERY annoying if rng decides to give you 3 in a row
allow_duplicates = FALSE
/datum/hallucination/announcement/start()
var/list/hal_sender = SShallucinations.message_sender
for(var/mob/living/carbon/human/H in living_mob_list)
if(H.client && !player_is_antag(H, only_offstation_roles = TRUE)) //We're not going to add ninjas, mercs, borers, etc to prevent meta.
hal_sender += H
switch(rand(1,15))
if(1)
sound_to(holder, 'sound/AI/radiation.ogg')
to_chat(holder, "<h2 class='alert'>Anomaly Break</h2>")
to_chat(holder, SPAN_ALERT("Comfortable levels of radiation detected near the station. [pick(SShallucinations.hallucinated_phrases)] Please cower among the shielded maintenance burrows.")) //hallucinated phrases contains the punctuation
if(2)
sound_to(holder, 'sound/AI/strangeobject.ogg')
to_chat(holder, "<h2 class='alert'>Welcome Object</h2>")
to_chat(holder, SPAN_ALERT("Transport signature of [pick(adjectives)] origin detected in your path, an object appears to have been nesting aboard NSS Upsilon. [pick(SShallucinations.hallucinated_phrases)]"))
if(3)
sound_to(holder, 'sound/AI/scrubbers.ogg')
to_chat(holder, "<h2 class='alert'>Reminder: Backpressure Warning</h2>")
to_chat(holder, SPAN_ALERT("The scrubbers network is expecting \an [pick(adjectives)] surge. Some ejection of [pick(adjectives)] contents will occur."))
if(4)
sound_to(holder, 'sound/AI/emergencyshuttlecalled.ogg')
to_chat(holder, "<h2 class='alert'>Emergency Departure</h2>")
to_chat(holder, SPAN_ALERT("The emergency evacuation shuttle has arrived. It will depart in approximately two minutes. Please do not allow [holder] to board."))
if(5)
sound_to(holder, 'sound/AI/vermin.ogg')
to_chat(holder, "<h2 class='alert'>Vermin Feast</h2>")
to_chat(holder, SPAN_ALERT("We indicate that [pick("rats", "lizards", "hivebots", "children")] have nested nearby. Free them before this starts to affect longetivity."))
if(6)
sound_to(holder, 'sound/AI/outbreak7.ogg')
to_chat(holder, "<h2 class='alert'>What have you done?</h2>")
to_chat(holder, SPAN_ALERT("Confirmed outbreak of help level 17 viral biohazard aboard [holder]. Help me. All personnel must destroy the outbreak. What have you helpME done?"))
to_chat(holder, SPAN_ALERT("-[pick(hal_sender)]"))
if(7)
sound_to(holder, 'sound/AI/meteors.ogg')
to_chat(holder, "<h2 class='alert'>Meteor Alarm</h2>")
to_chat(holder, SPAN_ALERT("A [pick(adjectives)] meteor storm has been authorized for a destruction course with your station. Less than three minutes until impact, shields cannot help you; seek shelter in the upper level."))
if(8)
sound_to(holder, pick('sound/AI/fungi.ogg', 'sound/AI/funguy.ogg', 'sound/AI/fun_guy.ogg', 'sound/AI/fun_gi.ogg'))
to_chat(holder, "<h2 class='alert'>Biohealth Notice</h2>")
to_chat(holder, SPAN_ALERT("Healthy fungi detected on station. Your bodies may be contaminated. This is mandatory, [holder]."))
if(9)
sound_to(holder, 'sound/effects/nuclearsiren.ogg')
to_chat(holder, "<font color='#008000'><b>Supermatter Monitor</b> states, \"WARNING: SUPERMATTER CRYSTAL DELAMINATION IMMINENT.\"</font>")
addtimer(CALLBACK(src, .proc/delam_call), 20)
addtimer(CALLBACK(src, .proc/delam_call), 35)
if(10 to 15) //Announcements that would be made by a player instead of random event
var/list/body = list(
"Please avoid [pick("medical", "security", "the bar", "engineering", "cargo")] at this time due to [pick("a k'ois outbreak.", "a hostage situation.", "hostile boarders.", "[holder].")]",
"Due to various complaints about [holder], we have conducted an investigation and due to the findings, we will [pick("arrest them. Please turn yourself in, [holder]", "terminate their employment with us.", "inform their family of their shortcomings.", "cyborgify them immediately.")]. Thank you.",
"[pick("Boarders have", "The AI has", "Intruders have")] demanded we sacrifice a crewmember to them. After [pick("much", "little", "quick")] deliberation, we have chosen [holder]. Please turn yourself over, or [pick("we", "your family", "all of us", "those you love")] will die.",
"Central Command has chosen [holder] as the NanoTrasen employee of the month! Everyone please congratulate them.",
"Everything is fine.",
"The tesla may or may not be loose.",
"This is your directive 11. [pick("Spiders have killed several crew.", "Boarders have taken a hostage.", "[holder] is armed and dangerous. Avoid them at all costs.", "Two black-suited individuals have taken items from the vault and armory.")]",
"Please stop [pick("drawing in blood. It's unsanitary.", "killing your fellow crew. It's rude.", "[holder] at all costs.", "falling down holes.")]",
"[holder] disappoints us all once again.")
sound_to(holder, 'sound/misc/announcements/notice.ogg')
to_chat(holder, "<h2 class='alert'>Station Announcement</h2>")
to_chat(holder, SPAN_ALERT(pick(body)))
to_chat(holder, SPAN_ALERT("-[pick(hal_sender)]"))
//for REALLY selling that fake delamination
/datum/hallucination/announcement/proc/delam_call()
var/list/people = list()
for(var/mob/living/carbon/human/M in living_mob_list)
if(!M.isMonkey() && !player_is_antag(M, only_offstation_roles = TRUE)) //Antag check prevents meta
people += M
people -= holder
if(!people.len)
return
var/radio_exclaim = pick("Oh SHIT!", "Oh fuck.", "Uhhh!", "That's not good!", "FUCK.", "Engineering?", "It's under control!", "We're fucked!", "Ohhhh boy.", "What?!", "Um, <b>what?!</b>")
to_chat(holder, "<font color='#008000'><b>[pick(people)]</b> says, \"[radio_exclaim]\"</font>")
/datum/hallucination/pda //fake PDA messages. this only plays the beep and sends something to chat; it won't show up in the PDA.
min_power = 20
duration = 900 //this duration length + not allowing duplicates prevents spamming messages on every valid handle_hallucination() which can get VERY annoying if rng decides to give you 3 in a row
allow_duplicates = FALSE
/datum/hallucination/pda/start()
var/list/sender = SShallucinations.message_sender
var/hall_job = "Unknown"
if(ishuman(holder))
var/mob/living/carbon/human/M = holder
hall_job = M.job
for(var/mob/living/carbon/human/H in living_mob_list)
if(H.client && !player_is_antag(H, only_offstation_roles = TRUE)) //adds current players to default list to provide variety. leaves out offstation antags.
sender += H
to_chat(holder, "<b>Message from [pick(sender)] to [holder.name] ([hall_job]),</b> \"[pick(SShallucinations.hallucinated_phrases)]\" (<FONT color = blue><u>reply</u></FONT>)")
sound_to(holder, 'sound/machines/twobeep.ogg')
//hallucinate someone else doing something.
/datum/hallucination/paranoia
var/list/hal_target = list() //The potential mob you're going to imagine doing this
/datum/hallucination/paranoia/can_affect(mob/living/carbon/C)
if(!..())
return FALSE
for(var/mob/living/M in oview(C))
if(!M.stat)
hal_target += M
if(hal_target.len)
return TRUE
/datum/hallucination/paranoia/start()
var/firstname = copytext(holder.real_name, 1, findtext(holder.real_name, " "))
var/t = pick(SShallucinations.hallucinated_actions)
t = replace_characters(t, list("you" = "[firstname]")) //the list contains items that say "you." This replaces "you" with the hallucinator's first name to sell the fact that the person is doing the emote.
to_chat(holder, "<b>[pick(hal_target)]</b> [t]")
/datum/hallucination/paranoia/second //Just so we get another chance at picking this.
/datum/hallucination/skitter
max_power = 60
/datum/hallucination/skitter/start()
to_chat(holder, "The spiderling skitters around.")
/datum/hallucination/prick
duration = 40
max_power = 35
/datum/hallucination/prick/can_affect(mob/living/carbon/C)
if(!..())
return FALSE
for(var/mob/living/M in oview(C, 1))
if(!M.stat)
return TRUE
/datum/hallucination/prick/start()
to_chat(holder,SPAN_NOTICE("You feel a tiny prick!"))
/datum/hallucination/prick/end() //chance to feel another effect after duration time
switch(rand(1,6))
if(1)
holder.druggy += min(holder.hallucination, 15)
if(2)
holder.make_dizzy(105)
if(3)
to_chat(holder,SPAN_GOOD("You feel good."))
..()
//the prick feeling but you actually imagine someone injecting you
/datum/hallucination/prick/by_person
min_power = HAL_POWER_LOW
max_power = INFINITY
duration = 20
var/injector
var/needle
var/list/prick_candidates = list()
/datum/hallucination/prick/by_person/start()
injector = pick(prick_candidates)
needle = pick("syringe", "hypospray", "pen")
to_chat(holder, SPAN_WARNING("\The [injector] is trying to inject \the [holder] with \the [needle]!"))
/datum/hallucination/prick/by_person/end()
to_chat(holder,SPAN_NOTICE("\The [injector] injects \the [holder] with \the [needle]!"))
to_chat(holder,SPAN_NOTICE("You feel a tiny prick!"))
..()
/datum/hallucination/insides
duration = 60
max_power = 75
/datum/hallucination/insides/start()
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
var/obj/O = pick(H.organs)
to_chat(holder,SPAN_DANGER("You feel something [pick("moving","squirming","skittering", "writhing", "burrowing", "crawling")] inside of your [O.name]!"))
else
to_chat(holder,SPAN_DANGER("You feel something [pick("moving","squirming","skittering", "writhing", "burrowing", "crawling")] inside of you!"))
if(prob(min(holder.hallucination/2, 80)))
sound_to(holder, pick('sound/misc/zapsplat/chitter1.ogg', 'sound/misc/zapsplat/chitter2.ogg', 'sound/effects/squelch1.ogg', 'sound/effects/lingextends.ogg'))
/datum/hallucination/insides/end()
if(prob(50))
to_chat(holder, SPAN_WARNING(pick("You see something moving under your skin!", "Whatever it is, it's definitely alive!", "If you don't get it out soon...", "It's moving towards your mouth!")))
..()
//Pain. Picks a random type of pain, and severity is based on their level of hallucination.
/datum/hallucination/pain
special_flags = NO_EMOTE
/datum/hallucination/pain/start()
var/pain_type = rand(1,5)
var/obj/item/organ/external/O
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
O = pick(H.organs)
O.add_pain(min(holder.hallucination / 3, 25)) //always cause fake pain
else
O = BP_CHEST
holder.adjustHalLoss(min(holder.hallucination / 3, 25)) //always cause fake pain
switch(pain_type)
if(1)
to_chat(holder,SPAN_DANGER("You feel a sharp pain in your head!"))
if(2)
switch(holder.hallucination)
if(1 to 15)
to_chat(holder, SPAN_WARNING("You feel a light pain in your [O.name]."))
if(16 to 49)
to_chat(holder, SPAN_DANGER("You feel a throbbing pain in your [O.name]!"))
if(HAL_POWER_MED to INFINITY)
to_chat(holder, SPAN_DANGER("You feel an excruciating pain in your [O.name]!"))
holder.emote("me",1,"winces.")
if(3)
switch(holder.hallucination)
if(1 to 15)
to_chat(holder, SPAN_WARNING("The muscles in your body hurt a little."))
if(16 to 49)
to_chat(holder, SPAN_DANGER("The muscles in your body cramp up painfully."))
if(HAL_POWER_MED to INFINITY)
to_chat(holder, SPAN_DANGER("There's pain all over your body!"))
holder.emote("me",1,"flinches as all the muscles in their body cramp up.")
if(4)
switch(holder.hallucination)
if(1 to 15)
to_chat(holder, SPAN_WARNING("Your [O.name] feels itchy."))
if(16 to 49)
to_chat(holder, SPAN_DANGER("You want to scratch the itch on your [O.name] badly!"))
if(HAL_POWER_MED to INFINITY)
to_chat(holder, SPAN_DANGER("You can't focus on anything but scratching the itch on your [O.name]!"))
holder.emote("me",1,"shivers slightly.")
if(5)
switch(holder.hallucination)
if(1 to 15)
to_chat(holder, SPAN_WARNING("You feel a little too warm."))
if(16 to 49)
to_chat(holder, SPAN_DANGER("You feel a horrible burning sensation on your [O.name]!"))
if(HAL_POWER_MED to INFINITY)
to_chat(holder, SPAN_DANGER("It feels like your [O.name] is being burnt to the bone!"))
holder.emote("me",1,"flinches.")
//sort of like the vampire friend messages.
/datum/hallucination/friendly
max_power = 45
special_flags = NO_THOUGHT
/datum/hallucination/friendly/start()
var/list/halpal = list()
for(var/mob/living/L in oview(holder))
halpal += L
if(halpal.len)
var/pal = pick(halpal)
var/list/halpal_emotes = list("[pal] looks trustworthy.",
"You feel as if [pal] is a relatively friendly individual.",
"You feel yourself paying more attention to what [pal] is saying.",
"[pal] has your best interests at heart, you can feel it.",
"A quiet voice tells you that [pal] should be considered a friend.",
"You never noticed until now how delightful [pal] is...",
"[pal] will keep you safe.",
"You feel captivated by [pal]'s charisma.",
"[pal] might as well be family to you.")
to_chat(holder, "<font color='green'><i>[pick(halpal_emotes)]</i></font>")
/datum/hallucination/passive
duration = 600 //minute fallback
allow_duplicates = FALSE
max_power = 55
/datum/hallucination/passive/can_affect(mob/living/carbon/C)
if(C.is_berserk())
return FALSE
if(C.disabilities & PACIFIST)
return FALSE
return ..()
/datum/hallucination/passive/start()
duration = rand(500, 700)
var/message = pick("You hurt so many people before... You have to stop.", "You won't hurt anyone ever again.", "Violence has caused so many problems. It's time to stop.", "The idea of conflict is terrifying!", "You realize that violence isn't the answer. Ever.", "You're struck by an overwhelming sense of guilt for your past acts of violence!")
to_chat(holder, SPAN_DANGER("A sudden realization surges to the forefront of your mind. [message]"))
holder.disabilities |= PACIFIST
for(var/i = 1; i <= 2; i++)
addtimer(CALLBACK(src, .proc/calm_feeling), rand(80, 150)*i)
/datum/hallucination/passive/end()
if(holder.disabilities & PACIFIST)
holder.disabilities &= ~PACIFIST
to_chat(holder, SPAN_NOTICE("You no longer feel passive."))
..()
/datum/hallucination/passive/proc/calm_feeling()
var/feeling = pick("You feel calm. It's so peaceful.", "Violence seems like such a strange idea to you.", "You feel relaxed and peaceful.", "A wave of calm washes over you as you feel all your anger leave you.", "You wonder why people waste their time fighting.", "It's fine. Everything's fine.", "You can't remember ever feeling angry.", "Nothing can hurt you as long as you don't hurt it.")
to_chat(holder, SPAN_GOOD(feeling))
/datum/hallucination/colorblind
min_power = HAL_POWER_LOW
duration = 100
allow_duplicates = FALSE
var/colorblindness
/datum/hallucination/colorblind/can_affect(mob/living/carbon/C)
if(C.client.color) //if they're already colorblind, we bail.
return FALSE
return ..()
/datum/hallucination/colorblind/start()
duration = rand(350, 750)
colorblindness = pick("deuteranopia", "protanopia", "tritanopia", "monochrome")
switch(colorblindness)
if("deuteranopia")
holder.add_client_color(/datum/client_color/deuteranopia)
if("protanopia")
holder.add_client_color(/datum/client_color/protanopia)
if("tritanopia")
holder.add_client_color(/datum/client_color/tritanopia)
if("monochrome")
holder.add_client_color(/datum/client_color/monochrome)
var/color_mes = pick("Everything looks... off.", "The colors shift around you.", "Wait, what happened to the colors?", "You watch as the colors around you swirl and shift.")
to_chat(holder, SPAN_GOOD(color_mes)) //Good span makes it stand out
/datum/hallucination/colorblind/end()
to_chat(holder, SPAN_GOOD("Slowly the colors around you shift back to what you feel is normal."))
if(holder)
switch(colorblindness)
if("deuteranopia")
holder.remove_client_color(/datum/client_color/deuteranopia)
if("protanopia")
holder.remove_client_color(/datum/client_color/protanopia)
if("tritanopia")
holder.remove_client_color(/datum/client_color/tritanopia)
if("monochrome")
holder.remove_client_color(/datum/client_color/monochrome)
..()
//imagining someone hits you.
/datum/hallucination/fakeattack
min_power = HAL_POWER_LOW
var/list/attacker_candidates = list()
/datum/hallucination/fakeattack/can_affect(mob/living/carbon/C)
if(!..())
return FALSE
for(var/mob/living/M in oview(C,1))
if(!M.stat)
attacker_candidates += M
if(attacker_candidates.len)
return TRUE
/datum/hallucination/fakeattack/start()
var/attacker = pick(attacker_candidates)
attacker_candidates -= attacker
if(prob(50))
to_chat(holder, SPAN_DANGER("[attacker] has hit [holder]!"))
sound_to(holder, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'))
else
to_chat(holder, SPAN_DANGER("[attacker] attempted to shove [holder]!"))
sound_to(holder, 'sound/weapons/thudswoosh.ogg')
//If we are hallucinating particularly hard and there's another person adjacent to us, we imagine they attack us, too.
if(holder.hallucination >= 70 && attacker_candidates.len)
attacker = pick(attacker_candidates)
if(prob(50))
to_chat(holder, SPAN_DANGER("[attacker] has hit [holder]!"))
sound_to(holder, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'))
else
to_chat(holder, SPAN_DANGER("[attacker] attempted to shove [holder]!"))
sound_to(holder, 'sound/weapons/thudswoosh.ogg')
/////////////////////////////////////////////
///// PEOPLE TALKING ABOUT OR TO YOU /////
/////////////////////////////////////////////
/datum/hallucination/talking
var/repeats = 2 //In total, we'll get two messages. We don't need to reset this number anywhere because on end() it's deleted and a new one will be created if it's chosen again in handle_hallucinations
special_flags = HEARING_DEPENDENT | NO_THOUGHT
/datum/hallucination/talking/can_affect(mob/living/carbon/C)
if(!..())
return FALSE
for(var/mob/living/M in oview(C))
if(!M.stat)
return TRUE
//Unique activate() since we are not adding the end() callback here; we're handling it in start() since it can loop
/datum/hallucination/talking/activate()
if(!holder || !holder.client)
return
holder.hallucinations += src
if(holder.hallucination >= 50)
repeats = 3
start()
////Talking about you. Most of it from Bay//////
/datum/hallucination/talking/start()
if(!can_affect(holder) || !holder || !repeats) //sanity check
end()
var/list/candidates = list()
for(var/mob/living/M in oview(holder))
if(!M.stat)
if(holder.hallucination >= 75) //If you're super fucked up you'll imagine more than just humans talking about you
candidates += M
else
if(ishuman(M))
candidates += M
if(!candidates.len) //No candidates, no effect.
end()
var/mob/living/talker = pick(candidates) //Who is talking to us?
var/message //What will they say?
//Name selection. This gives us variety. Sometimes it will be your last name, sometimes your first.
var/list/names = list()
var/lastname = copytext(holder.real_name, findtext(holder.real_name, " ")+1)
var/firstname = copytext(holder.real_name, 1, findtext(holder.real_name, " "))
if(lastname)
names += lastname
if(firstname)
names += firstname
if(!names.len)
names += holder.real_name
switch(rand(1,8)) //Deciding how we're going to manifest this hallucinated conversation.
if(1) //Nonverbal gesture.
to_chat(holder,"<B>[talker]</B> [pick("points", "looks", "stares", "smirks")] at [pick(names)] and says something softly.")
if(2 to 3) //Talking prompts imported from Bay. Less variation in these phrases, so we have less chance to pick them. Mitigates some repetition.
//message prep
var/add = prob(20) ? ", [pick(names)]" : "" //Accompanies phrases list. 20% chance to add the first or last name to the phrase for variation
var/list/phrases = list("Get out[add]!","Go away[add].","What are you doing[add]?","Where's your ID[add]?", "You know I love you[add].", "You do great work[add]!") //this is the phrase. [add] is chosen in the previous line.
if(holder.hallucination > 50) //If you're very messed up, the message variety gets a little more aggressive by adding these options
phrases += list("What did you come here for[add]?","Don't touch me[add].","You're not getting out of here[add].", "You're a failure, [pick(names)].","Just kill yourself already, [pick(names)].","Put on some clothes[add].","You're a horrible person[add].","You know nobody wants you here, right[add]?")
message = pick(phrases)
to_chat(holder,"<span class='game say'><B>[talker]</B> [talker.say_quote(message)], <span class='message'><span class='body'>\"[message]\"</span></span></span>")
else //More varied messages using text list and different speech prefixes
//message prep
var/speak_prefix = pick("Hey", "Uh", "Um", "Oh", "Ah", "") //For variety, we have a different greeting. This one has a chance of picking a starter....
speak_prefix = "[speak_prefix][pick(names)][pick(".","!","?")]" //...then adds the name, and ends it randomly with ., !, or ? ("Hey, name?" "Oh, name!" "Ah, name." "Name!"") etc.
message = prob(70) ? "[speak_prefix] [pick(SShallucinations.hallucinated_phrases)]" : pick(SShallucinations.hallucinated_phrases) //Here's the message that uses the hallucinated_phrases text list. Won't always apply the speak_prefix; sometimes they say weird shit without addressing you.
to_chat(holder,"<span class='game say'><B>[talker]</B> [talker.say_quote(message)], <span class='message'><span class='body'>\"[message]\"</span></span></span>")
repeats -= 1
if(repeats) //And we do it all over again, one or two more times.
addtimer(CALLBACK(src, .proc/start), rand(50, 100))
else
end()
//Thinking people are whispering messages to you.
/datum/hallucination/whisper
special_flags = HEARING_DEPENDENT
/datum/hallucination/whisper/can_affect(mob/living/carbon/C)
if(!..())
return FALSE
for(var/mob/living/M in oview(C, 1))
if(!M.stat)
return TRUE
/datum/hallucination/whisper/start()
var/list/whisper_candidates = list()
for(var/mob/living/M in oview(holder, 1))
if(!M.stat)
whisper_candidates += M
if(whisper_candidates.len)
var/whisperer = pick(whisper_candidates)
if(prob(70))
to_chat(holder, "<B>[whisperer]</B> whispers, <I>\"[pick(SShallucinations.hallucinated_phrases)]\"</I>")
else
to_chat(holder, "<B>[whisperer]</B> [pick("gently nudges", "pokes at", "taps", "looks at", "pats")] [holder], trying to get their attention.")
//whispers that don't depend on a person's proximity
/datum/hallucination/whisper/no_entity
min_power = HAL_POWER_LOW
/datum/hallucination/whisper/no_entity/can_affect(mob/living/carbon/C)
return ..()
/datum/hallucination/whisper/no_entity/start()
var/list/whisper_candidates = list("A familiar voice", "A distant voice", "A child's voice", "Something inside your head", "Your own voice", "A ghastly voice")
to_chat(holder, "<B>[pick(whisper_candidates)]</B> whispers directly into your mind, <I>\"[pick(SShallucinations.hallucinated_phrases)]\"</I>")
sound_to(holder, pick('sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg', 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg'))
holder.emote("me",1,"shivers.")
+188
View File
@@ -0,0 +1,188 @@
/datum/hallucination/mirage
max_power = HAL_POWER_LOW
duration = 120
var/number = 3
var/list/mirages = list()
/datum/hallucination/mirage/start()
duration = rand(100, 150)
var/list/possible_points = list()
for(var/turf/simulated/floor/F in view(holder, world.view+1))
possible_points += F
if(possible_points.len)
for(var/i = 1; i <= number; i++)
var/image/thing = generate_mirage()
mirages += thing
thing.loc = pick(possible_points)
holder.client.images += mirages
/datum/hallucination/mirage/Destroy()
if(holder.client)
holder.client.images -= mirages
. = ..()
/datum/hallucination/mirage/proc/generate_mirage()
var/icon/T = new('icons/obj/trash.dmi')
return image(T, pick(T.IconStates()), layer = OBJ_LAYER)
/datum/hallucination/mirage/end()
if(holder.client)
holder.client.images -= mirages
..()
/datum/hallucination/mirage/bleeding
min_power = HAL_POWER_LOW
max_power = INFINITY
duration = 350
allow_duplicates = FALSE
number = 4
var/obj/item/organ/external/part = "chest"
/datum/hallucination/mirage/bleeding/start()
number = min(round(holder.hallucination/10), 7) //cap at 7 times for duration's sake
for(var/i = 1; i <= number; i++)
addtimer(CALLBACK(src, .proc/show_mirage), rand(30,50)*i) //every 3 to 5 seconds
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
part = pick(H.organs)
to_chat(holder, SPAN_DANGER("The flesh on your [part.name] splits open. It doesn't hurt, but the blood won't stop coming..."))
/datum/hallucination/mirage/bleeding/generate_mirage()
var/image/I
if(prob(min(holder.hallucination, 80)))
I = image('icons/effects/blood.dmi', pick("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5", "mfloor6", "mfloor7"), layer = TURF_LAYER)
else
var/icon/T = new('icons/effects/drip.dmi')
I = image(T, pick(T.IconStates()), layer = TURF_LAYER)
I.color = holder.species?.blood_color
return I
/datum/hallucination/mirage/bleeding/proc/show_mirage()
var/image/thing = generate_mirage()
mirages += thing
thing.loc = get_turf(holder)
holder.client.images += thing //one at a time
if(prob(20))
var/list/message_picks = list("It won't stop, it won't stop...!", "You're feeling lightheaded...", "Your [part.name] won't stop gushing blood!", "The blood is everywhere!", "Everything around you is soaked with your blood...!")
to_chat(holder, SPAN_DANGER(pick(message_picks)))
/datum/hallucination/mirage/bleeding/end()
to_chat(holder, SPAN_WARNING("The flesh on your [part.name] suddenly appears whole again. You can't see the blood anymore, but the scent of it lingers heavily in the air."))
..()
/datum/hallucination/mirage/horror
min_power = HAL_POWER_HIGH
max_power = INFINITY
number = 1
/datum/hallucination/mirage/horror/start()
..()
to_chat(holder, SPAN_WARNING("The horror [pick("gnashes", "lunges", "shrieks")] at [holder]!"))
/datum/hallucination/mirage/horror/end()
to_chat(holder, SPAN_WARNING("With a final shriek that seems to originate from within your mind, the entity fades away."))
sound_to(holder, pick('sound/hallucinations/wail.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/effects/creepyshriek.ogg'))
..()
/datum/hallucination/mirage/horror/generate_mirage()
var/icon/T = new('icons/mob/npc/animal.dmi')
return image(T, pick("abomination", "lesser_ling", "faithless", "otherthing"), layer = MOB_LAYER)
/datum/hallucination/mirage/carnage
min_power = HAL_POWER_LOW
max_power = INFINITY
number = 10
/datum/hallucination/mirage/carnage/start()
if(holder.hallucination >= HAL_POWER_HIGH) //Heavily hallucinating will increase the amount of horrific carnage we witness
number = 20
..()
/datum/hallucination/mirage/carnage/generate_mirage()
if(prob(50))
var/image/I = image('icons/effects/blood.dmi', pick("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7"), layer = TURF_LAYER)
var/list/blood_picks = list("#1D2CBF" = 0.1, "#E6E600" = 0.1, "#A10808" = 0.8) //skrell, vaurca, human. most likely to pick regular red
I.color = pickweight(blood_picks)
return I
else
var/image/I = image('icons/obj/ammo.dmi', "s-casing-spent", layer = OBJ_LAYER)
I.layer = TURF_LAYER
I.dir = pick(alldirs)
I.pixel_x = rand(-10,10)
I.pixel_y = rand(-10,10)
return I
/datum/hallucination/mirage/anomaly
min_power = 40
max_power = INFINITY
number = 1
/datum/hallucination/mirage/anomaly/start()
..()
to_chat(holder, SPAN_WARNING("With a small crackle, the [pick("entity", "idol", "device")] manifests!"))
sound_to(holder, 'sound/effects/stealthoff.ogg')
/datum/hallucination/mirage/anomaly/generate_mirage()
var/istate = pick("ano01", "ano11", "ano21", "ano31", "ano41", "ano81", "ano121")
var/image/I = image('icons/obj/xenoarchaeology.dmi', istate, layer = OBJ_LAYER)
return I
/datum/hallucination/mirage/anomaly/end()
to_chat(holder, SPAN_WARNING("With a loud zap, the [pick("entity", "idol", "device")] is sucked through a rift in bluespace!"))
sound_to(holder, 'sound/effects/phasein.ogg')
..()
/datum/hallucination/mirage/viscerator
min_power = 40
max_power = INFINITY
number = 3
/datum/hallucination/mirage/viscerator/start()
addtimer(CALLBACK(src, .proc/buzz), rand(30, 60))
..()
/datum/hallucination/mirage/viscerator/generate_mirage()
var/image/I = image('icons/mob/npc/aibots.dmi', "viscerator_attack", layer = OBJ_LAYER)
return I
/datum/hallucination/mirage/viscerator/proc/buzz()
to_chat(holder, "The viscerator buzzes at [holder].")
/datum/hallucination/mirage/eyes
min_power = HAL_POWER_MED
max_power = INFINITY
number = 6
/datum/hallucination/mirage/eyes/start()
if(holder.hallucination >= 100)
number = 15
..()
/datum/hallucination/mirage/eyes/generate_mirage()
var/icon/T = new('icons/obj/eyes.dmi')
return image(T, pick(T.IconStates()), layer = OBJ_LAYER)
/datum/hallucination/mirage/narsie
min_power = 5000 //this level of hallucination is only possible on the 2 last stages of your mind breaking during cult conversions. Or admin fuckery
max_power = INFINITY
number = 1
duration = 30
/datum/hallucination/mirage/narsie/generate_mirage()
var/image/T = image('icons/obj/narsie.dmi', "narsie-small-chains", layer = MOB_LAYER+0.01)
return T
+168
View File
@@ -0,0 +1,168 @@
/datum/hallucination/mindread
allow_duplicates = FALSE
min_power = HAL_POWER_MED
special_flags = NO_THOUGHT | NO_EMOTE
/datum/hallucination/mindread/can_affect(mob/living/carbon/C)
if(C.psi) //Don't give it to people who already have psi powers
return FALSE
if(locate(/datum/hallucination/telepathy) in C.hallucinations)
return FALSE
return ..()
/datum/hallucination/mindread/activate()
..()
addtimer(CALLBACK(src, .proc/mind_give), rand(30, 50))
//set duration, foreshadow powers
/datum/hallucination/mindread/start()
duration = rand(2, 4) MINUTES
switch(rand(1, 3))
if(1)
sound_to(holder, 'sound/misc/announcements/notice.ogg')
to_chat(holder, "<h2 class='alert'>Ion Storm?</h2>")
to_chat(holder, SPAN_ALERT("It has come to our attention that the station has passed through an unusual ion storm. Several crewmembers are exhibiting unusual abilities."))
if(2)
sound_to(holder, 'sound/hallucinations/behind_you1.ogg')
to_chat(holder, SPAN_GOOD("You hear a whispering in your mind. A promise of [pick("power", "enlightenment", "sight beyond sight", "knowledge terrible but true")]. Your vision goes white for a moment; when it returns, you feel... different."))
flick("e_flash", holder.flash)
if(3)
to_chat(holder, FONT_LARGE(SPAN_DANGER("You feel a sudden pain in your head, as if it's being ripped in two! When it subsides to a dull throbbing a moment later, you feel... different.")))
holder.emote("me",1,"winces.")
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
var/obj/item/organ/external/O = H.get_organ(BP_HEAD)
O.add_pain(25)
//grant powers
/datum/hallucination/mindread/proc/mind_give()
to_chat(holder, SPAN_NOTICE(FONT_LARGE("<B>You have developed a psionic gift!</B>")))
to_chat(holder, SPAN_NOTICE("You can feel your mind surging with power! Check the abilities tab to use your new power!"))
holder.verbs += /mob/living/carbon/proc/fakemindread
/datum/hallucination/mindread/end()
if(holder)
holder.verbs -= /mob/living/carbon/proc/fakemindread
to_chat(holder, SPAN_NOTICE("<b>Your psionic powers vanish abruptly, leaving you cold and empty.</b>"))
..()
/mob/living/carbon/proc/fakemindread()
set name = "Read Mind"
set category = "Abilities"
if(!hallucination)
for(var/datum/hallucination/mindread/H in hallucinations)
H.end()
return
if(use_check_and_message(usr))
to_chat(usr, SPAN_WARNING("You're not in any state to use your powers right now!"))
return
var/list/creatures = list()
for(var/mob/living/C in oview(usr))
creatures += C
if(!creatures.len)
return
var/mob/target = input("Whose mind do you wish to probe?") as null|anything in creatures
if(!target)
return
if(target.stat)
to_chat(usr, SPAN_WARNING("\The [target]'s mind is not in any state to be probed!"))
return
to_chat(usr, SPAN_NOTICE("<b>You dip your mentality into the surface layer of \the [target]'s mind, seeking a prominent thought.</b>"))
if(do_after(usr, 30))
sleep(rand(50, 120))
usr.visible_message("<B>[usr]</B> puts [usr.get_pronoun(1)] hands to [usr.get_pronoun(1)] head and mumbles incoherently as they stare, unblinking, at \the [target].",
SPAN_NOTICE("<b>You skim thoughts from the surface of \the [target]'s mind: \"<i>[pick(SShallucinations.hallucinated_phrases)]</i>\"</b>"))
else
to_chat(usr, SPAN_WARNING("You need to stay still to focus your energy!"))
//Fake telepathy, inspired by and mostly ported from Bay's
/datum/hallucination/telepathy
min_power = HAL_POWER_HIGH
allow_duplicates = FALSE
special_flags = NO_THOUGHT | NO_EMOTE
/datum/hallucination/telepathy/can_affect(mob/living/carbon/C)
if(C.psi) //Don't give it to people who already have psi powers
return FALSE
if(locate(/datum/hallucination/mindread) in C.hallucinations)
return FALSE
return ..()
/datum/hallucination/telepathy/activate()
..()
addtimer(CALLBACK(src, .proc/tele_give), rand(30, 50))
/datum/hallucination/telepathy/start()
duration = rand(2, 4) MINUTES
switch(rand(1, 3))
if(1)
sound_to(holder, 'sound/misc/announcements/notice.ogg')
to_chat(holder, "<h2 class='alert'>Ion Storm?</h2>")
to_chat(holder, SPAN_ALERT("It has come to our attention that the station has passed through an unusual ion storm. Several crewmembers are exhibiting unusual abilities."))
if(2)
sound_to(holder, 'sound/hallucinations/behind_you1.ogg')
to_chat(holder, SPAN_GOOD("You hear a whispering in your mind. A promise of [pick("power", "enlightenment", "sight beyond sight", "knowledge terrible but true")]. Your vision goes white for a moment; when it returns, you feel... different."))
flick("e_flash", holder.flash)
if(3)
to_chat(holder, FONT_LARGE(SPAN_DANGER("You feel a sudden pain in your head, as if it's being ripped in two! When it subsides to a dull throbbing a moment later, you feel... different.")))
holder.emote("me",1,"winces.")
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
var/obj/item/organ/external/O = H.get_organ(BP_HEAD)
O.add_pain(25)
//grant powers
/datum/hallucination/telepathy/proc/tele_give()
to_chat(holder, SPAN_NOTICE(FONT_LARGE("<B>You have developed a psionic gift!</B>")))
to_chat(holder, SPAN_NOTICE("You can feel your mind surging with power! Check the abilities tab to use your new power!"))
holder.verbs += /mob/living/carbon/proc/faketelepathy
/datum/hallucination/telepathy/end()
if(holder)
holder.verbs -= /mob/living/carbon/proc/faketelepathy
to_chat(holder, SPAN_NOTICE("<b>Your psionic powers vanish abruptly, leaving you cold and empty.</b>"))
..()
/mob/living/carbon/proc/faketelepathy()
set name = "Send Telepathic Message"
set category = "Abilities"
if(!hallucination)
for(var/datum/hallucination/telepathy/H in hallucinations)
H.end()
return
if(use_check_and_message(usr))
to_chat(usr, SPAN_WARNING("You're not in any state to use your powers right now!"))
return
var/list/creatures = list()
for(var/mob/living/C in oview(usr))
creatures += C
if(!creatures.len)
return
var/mob/target = input("Who do you wish to send a message to?") as null|anything in creatures
if(!target)
return
if(target.stat)
to_chat(usr, SPAN_WARNING("\The [target]'s mind is not in any state to receive messages!"))
return
var/message = sanitizeSafe(input("Enter your message."), MAX_MESSAGE_LEN)
if(!message)
return
to_chat(usr, SPAN_NOTICE("<b>You focus your mental energy and begin projecting your message into the mind of \the [target]...</b>"))
if(do_after(usr, 30))
usr.visible_message("<span class='game say'><span class='name'>[usr]</span> [usr.say_quote(message)], <span class='message'><span class='body'>\"[message]\"</span></span></span>",
SPAN_NOTICE("<b>You feel your message enter \the [target]'s mind!</b>"))
else
to_chat(usr, SPAN_WARNING("You need to stay still to focus your efforts!"))
+105
View File
@@ -0,0 +1,105 @@
/datum/hallucination/sound
max_power = 40
special_flags = HEARING_DEPENDENT
var/list/sounds = list('sound/weapons/smash.ogg',
'sound/weapons/flash_ring.ogg',
'sound/effects/Explosion1.ogg',
'sound/effects/Explosion2.ogg',
'sound/effects/explosionfar.ogg',
'sound/effects/crusher_alarm.ogg',
'sound/effects/smoke.ogg')
/datum/hallucination/sound/start()
sound_to(holder, pick(sounds))
/datum/hallucination/sound/echo
duration = 50 //This delays end() by 5 seconds, where we have a chance of playing another sound from this list.
max_power = HAL_POWER_HIGH
sounds = list('sound/machines/airlock.ogg',
'sound/voice/shriek1.ogg',
'sound/misc/nymphchirp.ogg',
'sound/machines/twobeep.ogg',
'sound/machines/windowdoor.ogg',
'sound/effects/glass_break1.ogg',
'sound/weapons/railgun.ogg',
'sound/effects/phasein.ogg',
'sound/effects/sparks1.ogg',
'sound/effects/sparks2.ogg',
'sound/effects/sparks3.ogg',
'sound/effects/stealthoff.ogg',
'sound/misc/zapsplat/chitter1.ogg',
'sound/misc/zapsplat/chitter2.ogg',
'sound/effects/squelch1.ogg',
'sound/items/Ratchet.ogg',
'sound/items/Welder.ogg',
'sound/items/Crowbar.ogg',
'sound/items/Screwdriver.ogg',
'sound/items/drill_use.ogg',
'sound/items/air_wrench.ogg')
/datum/hallucination/sound/echo/end()
if(prob(holder.hallucination / 2))
sound_to(holder, pick(sounds))
..()
/datum/hallucination/sound/creepy
min_power = HAL_POWER_MED
max_power = INFINITY
special_flags = null //These are spooky enough to happen even when deaf
sounds = list('sound/effects/ghost.ogg',
'sound/effects/ghost2.ogg',
'sound/effects/screech.ogg',
'sound/effects/creepyshriek.ogg',
'sound/hallucinations/behind_you1.ogg',
'sound/hallucinations/behind_you2.ogg',
'sound/hallucinations/far_noise.ogg',
'sound/hallucinations/growl1.ogg',
'sound/hallucinations/growl2.ogg',
'sound/hallucinations/growl3.ogg',
'sound/hallucinations/im_here1.ogg',
'sound/hallucinations/im_here2.ogg',
'sound/hallucinations/i_see_you1.ogg',
'sound/hallucinations/i_see_you2.ogg',
'sound/hallucinations/look_up1.ogg',
'sound/hallucinations/look_up2.ogg',
'sound/hallucinations/over_here1.ogg',
'sound/hallucinations/over_here2.ogg',
'sound/hallucinations/over_here3.ogg',
'sound/hallucinations/turn_around1.ogg',
'sound/hallucinations/turn_around2.ogg',
'sound/hallucinations/veryfar_noise.ogg',
'sound/hallucinations/wail.ogg')
/datum/hallucination/sound/reaction
min_power = 20
max_power = INFINITY
special_flags = null
/datum/hallucination/sound/reaction/start()
switch(rand(1,3))
if(1) //Nearmiss
sound_to(holder, 'sound/weapons/gunshot/gunshot_light.ogg')
to_chat(holder, SPAN_DANGER("Something zips by your head, barely missing you!")) //phantom reflex to audio
shake_camera(holder, 3, 1)
if(2) //Gunshot
sound_to(holder, 'sound/weapons/gunshot/gunshot1.ogg')
if(ishuman(holder))
var/mob/living/carbon/human/H = holder
var/obj/item/organ/external/O = pick(H.organs)
O.add_pain(15)
to_chat(holder, SPAN_DANGER("You feel a sharp pain in your [O.name]!")) //phantom pain reaction to audio
else
holder.adjustHalLoss(15)
to_chat(holder, SPAN_DANGER("You feel a sharp pain in your chest!"))
shake_camera(holder, 3, 1)
if(prob(holder.hallucination))
holder.eye_blurry += 8
if(3) //Don't tase me bro
sound_to(holder, 'sound/weapons/Taser.ogg')
to_chat(holder, SPAN_DANGER("You feel numb as a shock courses through your body!")) //phantom pain reaction to audio
holder.adjustHalLoss(20)
if(prob(holder.hallucination))
holder.eye_blind += 4
+5 -20
View File
@@ -735,23 +735,8 @@
silent = 0
return 1
if(hallucination)
//Machines do not hallucinate.
if(hallucination >= 20 && !(species.flags & (NO_POISON|IS_PLANT)))
if(prob(3))
fake_attack(src)
if(!handling_hal)
spawn handle_hallucinations() //The not boring kind!
if(hallucination<=2)
hallucination = 0
adjustHalLoss(0)
else
hallucination -= 2
else
for(var/atom/a in hallucinations)
qdel(a)
if(hallucination && !(species.flags & (NO_POISON|IS_PLANT)))
handle_hallucinations()
if(get_shock() >= (species.total_health * 0.75))
if(!stat)
@@ -777,7 +762,7 @@
//Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar.
if(client || sleeping > 3 || istype(bg))
AdjustSleeping(-1)
if(prob(2) && health && !hal_crit && !failed_last_breath && !isSynthetic())
if(prob(2) && health && !failed_last_breath && !isSynthetic())
if(!paralysis)
emote("snore")
else
@@ -986,12 +971,12 @@
pressure.icon_state = new_pressure
if(toxin)
var/new_tox = (hal_screwyhud == 4 || phoron_alert) ? "tox1" : "tox0"
var/new_tox = (phoron_alert) ? "tox1" : "tox0"
if (toxin.icon_state != new_tox)
toxin.icon_state = new_tox
if(oxygen)
var/new_oxy = (hal_screwyhud == 3 || oxygen_alert) ? "oxy1" : "oxy0"
var/new_oxy = (oxygen_alert) ? "oxy1" : "oxy0"
if (oxygen.icon_state != new_oxy)
oxygen.icon_state = new_oxy
@@ -12,7 +12,6 @@
var/remote_network // The network this mob is attached to, used in virtual reality and remote control things
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
var/list/atom/hallucinations = list() //A list of hallucinated people that try to attack the mob. See /obj/effect/fake_attacker in hallucinations.dm
var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out.
@@ -153,7 +153,7 @@
if(remove_generic)
M.drowsyness = max(0, M.drowsyness - 6 * removed)
M.hallucination += (-9 * removed)
M.hallucination -= (9 * removed)
M.add_up_to_chemical_effect(CE_ANTITOXIN, 1)
var/removing = (4 * removed)
@@ -0,0 +1,19 @@
# Your name.
author: Doxxmedearly
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
changes:
- rscadd: "Hallucination handling has been totally overhauled by taking, modifying and tremendously expanding on Bay's system. Goodbye, 2012 hallucination code."
- rscdel: "Removed the following hallucination effects: Fake HUD updates, items spawning in your hand, 'fake death', and pun-pun attacking you."
- rscadd: "Added over a dozen new categories of potential hallucination effects. Some are subtle, some are more overt. Increased the variety of previously-existing hallucination effects."
- rscadd: "Added several large lists of prompts that should keep hallucinations varied and interesting for a long time. These can also easily be expanded upon!"
- tweak: "Sounds will have less reverb while hallucinating, so you probably won't need to tear your headset off while resisting a cult conversion."
- backend: "Created a subsystem for hallucinations. Larger prompt lists were added as text files."