diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 859f3e37756..21406c0e43a 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -9,6 +9,7 @@
#define INVESTIGATE_SUPERMATTER "supermatter"
#define INVESTIGATE_TELESCI "telesci"
#define INVESTIGATE_WIRES "wires"
+#define INVESTIGATE_HALLUCINATIONS "hallucinations"
//Individual logging defines
#define INDIVIDUAL_ATTACK_LOG "Attack log"
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 7b399879c57..4fe57be4429 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -942,7 +942,7 @@
var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in hallucinations
if(!usr)
return
- if(!C)
+ if(QDELETED(C))
to_chat(usr, "Mob doesn't exist anymore")
return
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 007f8e42bdc..94047727bc0 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -233,9 +233,13 @@
return
else /*if(src.justzap)*/
return
- else if(user.hallucination > 50 && ishuman(user) && prob(4) && !operating)
- hallucinate_shock(user)
- return
+ else if(user.hallucinating() && ishuman(user) && prob(4) && !operating)
+ var/mob/living/carbon/human/H = user
+ if(H.gloves)
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.siemens_coefficient)//not insulated
+ hallucinate_shock(H)
+ return
if (cyclelinkedairlock)
if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed(user))
if(cyclelinkedairlock.operating)
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 0e91b3c0f12..d0ee90e4d39 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -5,7 +5,7 @@
F << "[time_stamp()] \ref[src] ([x],[y],[z]) || [src] [message]
"
-/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY) )
+/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS) )
set name = "Investigate"
set category = "Admin"
if(!holder)
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 8633b89f006..2b8fe4b0642 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -60,9 +60,14 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
var/halpick = pick(current)
new halpick(src, FALSE)
+/mob/living/carbon/proc/set_screwyhud(hud_type)
+ hal_screwyhud = hud_type
+ update_health_hud()
+
/datum/hallucination
var/mob/living/carbon/target
var/cost = 5 //affects the amount of hallucination reduced, and cooldown until the next hallucination
+ var/feedback_details //extra info for investigate
/datum/hallucination/New(mob/living/carbon/T, forced = TRUE)
set waitfor = 0
@@ -72,9 +77,13 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
target.next_hallucination = world.time + (rand(cost * 0.5, cost * 3) * 10)
/datum/hallucination/proc/wake_and_restore()
- target.hal_screwyhud = SCREWYHUD_NONE
+ target.set_screwyhud(SCREWYHUD_NONE)
target.SetSleeping(0)
+/datum/hallucination/Destroy()
+ target.investigate_log("was afflicted with a hallucination of type [type]. [feedback_details]", INVESTIGATE_HALLUCINATIONS)
+ return ..()
+
/obj/effect/hallucination
invisibility = INVISIBILITY_OBSERVER
var/mob/living/carbon/target = null
@@ -152,6 +161,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
if(!U.welded)
center = get_turf(U)
break
+ feedback_details += "Vent Coords: [center.x],[center.y],[center.z]"
flood_images += image(image_icon,center,image_state,MOB_LAYER)
flood_turfs += center
if(target.client) target.client.images |= flood_images
@@ -217,6 +227,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
if(!U.welded)
pump = U
break
+ feedback_details += "Vent Coords: [pump.x],[pump.y],[pump.z]"
if(pump)
xeno = new(pump.loc,target)
sleep(10)
@@ -265,6 +276,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
break
if(!wall)
return INITIALIZE_HINT_QDEL
+ feedback_details += "Source: [wall.x],[wall.y],[wall.z]"
fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER)
var/turf/landing = get_turf(target)
@@ -317,6 +329,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
var/screen_border = pick(SOUTH,EAST,WEST,NORTH)
for(var/i in 1 to 13)
start = get_step(start,screen_border)
+ feedback_details += "Source: [start.x],[start.y],[start.z]"
s = new(start,target)
s.parent = src
for(var/i in 1 to 13)
@@ -337,18 +350,21 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
/obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir)
var/target_dist = get_dist(src,target)
if(target_dist<=3) //"Eaten"
- target.hal_screwyhud = SCREWYHUD_DEAD
+ target.set_screwyhud(SCREWYHUD_DEAD)
target.SetUnconscious(160)
addtimer(CALLBACK(parent, /datum/hallucination/.proc/wake_and_restore), rand(30, 50))
/datum/hallucination/battle
cost = 15
-/datum/hallucination/battle/New(mob/living/carbon/T, forced = TRUE)
+/datum/hallucination/battle/New(mob/living/carbon/T, forced = TRUE, battle_type)
..()
var/hits = rand(3,6)
- switch(rand(1,5))
- if(1) //Laser fight
+ if(!battle_type)
+ battle_type = pick("laser","esword","gun","stunprod","bomb")
+ feedback_details += "Type: [battle_type]"
+ switch(battle_type)
+ if("laser") //Laser fight
for(var/i in 1 to hits)
target.playsound_local(null, 'sound/weapons/laser.ogg', 25, 1)
if(prob(50))
@@ -357,14 +373,14 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/effects/searwall.ogg', 25, 1), rand(10,20))
sleep(rand(CLICK_CD_RANGE, CLICK_CD_RANGE + 8))
target.playsound_local(null, get_sfx("bodyfall"), 25, 1)
- if(2) //Esword fight
+ if("esword") //Esword fight
target.playsound_local(null, 'sound/weapons/saberon.ogg',15, 1)
for(var/i=0,idoor_number && door_number>0)
break
@@ -734,7 +759,9 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
people += H
if(person) //Basic talk
var/image/speech_overlay = image('icons/mob/talk.dmi', person, "default0", layer = ABOVE_MOB_LAYER)
- to_chat(target, target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans()))
+ var/message = target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans())
+ feedback_details += "Type: Talk, Source: [person.real_name], Message: [message]"
+ to_chat(target, message)
if(target.client)
target.client.images |= speech_overlay
sleep(30)
@@ -744,7 +771,9 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
humans += H
person = pick(humans)
- to_chat(target, target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans()))
+ var/message = target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans())
+ feedback_details += "Type: Radio, Source: [person.real_name], Message: [message]"
+ to_chat(target, message)
qdel(src)
/datum/hallucination/message
@@ -763,43 +792,48 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
"You're hallucinating.", \
//Direct advice
"[pick_list_replacements(HAL_LINES_FILE, "advice")]")
+ feedback_details += "Message: [chosen]"
to_chat(target, chosen)
qdel(src)
/datum/hallucination/sounds
cost = 15
-/datum/hallucination/sounds/New(mob/living/carbon/T, forced = TRUE)
+/datum/hallucination/sounds/New(mob/living/carbon/T, forced = TRUE, sound_type)
..()
+ if(!sound_type)
+ sound_type = pick("airlock","explosion","far_explosion","glass","phone","summon_guns","alarm","beepsky","hallelujah","creepy","ratvar","shuttle_dock",
+ "wall_decon","door_hack","esword","blob_alert","tesla","malf_ai")
+ feedback_details += "Type: [sound_type]"
//Strange audio
- switch(rand(1,20))
- if(1)
+ switch(sound_type)
+ if("airlock")
target.playsound_local(null,'sound/machines/airlock.ogg', 15, 1)
- if(2)
+ if("explosion")
if(prob(50))
target.playsound_local(null,'sound/effects/explosion1.ogg', 50, 1)
else
target.playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1)
- if(3)
+ if("far_explosion")
target.playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1)
- if(4)
+ if("glass")
target.playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1)
- if(5)
+ if("phone")
target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
sleep(15)
target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
sleep(15)
target.playsound_local(null, 'sound/weapons/ring.ogg', 35)
- if(6)
+ if("summon_guns")
target.playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1)
- if(7)
+ if("alarm")
target.playsound_local(null, 'sound/machines/alarm.ogg', 100, 0)
- if(8)
+ if("beepsky")
target.playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0)
- if(9)
+ if("hallelujah")
target.playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50)
//Rare audio
- if(10)
+ if("creepy")
//These sounds are (mostly) taken from Hidden: Source
var/static/list/hallucinations_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',\
@@ -807,42 +841,42 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
'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')
target.playsound_local(null, pick(hallucinations_creepyasssounds), 50, 1)
- if(11)
+ if("ratvar")
target.playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100)
sleep(150)
target.playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100)
- if(12)
+ if("shuttle_dock")
to_chat(target, "Priority Announcement
")
to_chat(target, "
The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.
")
target.playsound_local(null, 'sound/ai/shuttledock.ogg', 100)
//Deconstructing a wall
- if(13)
+ if("wall_decon")
target.playsound_local(null, 'sound/items/welder.ogg', 15, 1)
sleep(105)
target.playsound_local(null, 'sound/items/welder2.ogg', 15, 1)
sleep(15)
target.playsound_local(null, 'sound/items/ratchet.ogg', 15, 1)
//Hacking a door
- if(14)
+ if("door_hack")
target.playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1)
sleep(rand(10,30))
for(var/i = rand(1,3), i>0, i--)
target.playsound_local(null, 'sound/weapons/empty.ogg', 15, 1)
sleep(rand(10,30))
target.playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1)
- if(15)
+ if("esword")
target.playsound_local(null, 'sound/weapons/saberon.ogg',35,1)
- if(16)
+ if("blob_alert")
to_chat(target, "Biohazard Alert
")
to_chat(target, "
Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.
")
target.playsound_local(null, 'sound/ai/outbreak5.ogg', 100, 0)
- if(17) //Tesla loose!
+ if("tesla") //Tesla loose!
target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1)
sleep(20)
target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1)
sleep(20)
target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1)
- if(18) //AI is doomsdaying!
+ if("malf_ai") //AI is doomsdaying!
to_chat(target, "Anomaly Alert
")
to_chat(target, "
Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.
")
target.playsound_local(null, 'sound/ai/aimalf.ogg', 100, 0)
@@ -854,9 +888,10 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
/datum/hallucination/hudscrew/New(mob/living/carbon/T, forced = TRUE)
..()
//Screwy HUD
- target.hal_screwyhud = pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY)
+ target.set_screwyhud(pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY))
+ feedback_details += "Type: [target.hal_screwyhud]"
sleep(rand(100,250))
- target.hal_screwyhud = SCREWYHUD_NONE
+ target.set_screwyhud(SCREWYHUD_NONE)
qdel(src)
/datum/hallucination/fake_alert
@@ -867,6 +902,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temphot","tempcold","pressure")
if(specific)
alert_type = specific
+ feedback_details += "Type: [alert_type]"
switch(alert_type)
if("oxy")
target.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE)
@@ -962,6 +998,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
target.halitem.icon = 'icons/obj/grenade.dmi'
target.halitem.icon_state = "flashbang1"
target.halitem.name = "Flashbang"
+ feedback_details += "Type: [target.halitem.name]"
if(target.client) target.client.screen += target.halitem
QDEL_IN(target.halitem, rand(150, 350))
qdel(src)
@@ -1006,7 +1043,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
/datum/hallucination/death/New(mob/living/carbon/T, forced = TRUE)
set waitfor = 0
..()
- target.hal_screwyhud = SCREWYHUD_DEAD
+ target.set_screwyhud(SCREWYHUD_DEAD)
target.Knockdown(300)
target.silent += 10
var/area/area = get_area(target)
@@ -1025,7 +1062,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
to_chat(target, "DEAD: [fakemob.name] says, \"[pick("rip","hey [target.first_name()]","you too?","is the AI rogue?",\
"i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"")
sleep(rand(70,90))
- target.hal_screwyhud = SCREWYHUD_NONE
+ target.set_screwyhud(SCREWYHUD_NONE)
target.SetKnockdown(0)
target.silent = 0
qdel(src)
@@ -1100,6 +1137,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
startlocs += T
var/turf/start = pick(startlocs)
var/proj_type = pick(subtypesof(/obj/item/projectile/hallucination))
+ feedback_details += "Type: [proj_type]"
var/obj/item/projectile/hallucination/H = new proj_type(start)
target.playsound_local(start, H.hal_fire_sound, 60, 1)
H.hal_target = target
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 1c07c408d38..3ae1b198f80 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -234,6 +234,12 @@
/mob/living/carbon/is_muzzled()
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
+/mob/living/carbon/hallucinating()
+ if(hallucination)
+ return TRUE
+ else
+ return FALSE
+
/mob/living/carbon/resist_buckle()
if(restrained())
changeNext_move(CLICK_CD_BREAKOUT)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index a704c2e43f0..46f5db920bc 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -325,6 +325,9 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
return B.eye_blind
return 0
+/mob/proc/hallucinating()
+ return FALSE
+
/proc/is_special_character(mob/M) // returns 1 for special characters and 2 for heroes of gamemode //moved out of admins.dm because things other than admin procs were calling this.
if(!SSticker.HasRoundStarted())
return 0
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 27cad406fab..3811512a021 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -101,9 +101,11 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "chem_dispenser", name, 550, 550, master_ui, state)
+ if(user.hallucinating())
+ ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals
ui.open()
-/obj/machinery/chem_dispenser/ui_data()
+/obj/machinery/chem_dispenser/ui_data(mob/user)
var/data = list()
data["amount"] = amount
data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI.
@@ -128,10 +130,16 @@
data["beakerTransferAmounts"] = null
var chemicals[0]
+ var/is_hallucinating = FALSE
+ if(user.hallucinating())
+ is_hallucinating = TRUE
for(var/re in dispensable_reagents)
var/datum/reagent/temp = GLOB.chemical_reagents_list[re]
if(temp)
- chemicals.Add(list(list("title" = temp.name, "id" = temp.id)))
+ var/chemname = temp.name
+ if(is_hallucinating && prob(5))
+ chemname = "[pick_list_replacements("hallucination.json", "chemicals")]"
+ chemicals.Add(list(list("title" = chemname, "id" = temp.id)))
data["chemicals"] = chemicals
return data
diff --git a/strings/hallucination.json b/strings/hallucination.json
index 03c2a21b854..b28c70db4a6 100644
--- a/strings/hallucination.json
+++ b/strings/hallucination.json
@@ -198,4 +198,32 @@
"You have my permission. Do it."
]
+ "chemicals": [
+ "Ooze",
+ "Fire",
+ "Earth",
+ "Lightning",
+ "Air",
+ "Magic",
+ "Spiders",
+ "Button",
+ "Surprise",
+ "Happiness",
+ "Despair",
+ "Blood",
+ "Awesome",
+ "Infinity",
+ "Electronics",
+ "Time",
+ "Space",
+ "Pain",
+ "Guts",
+ "Life",
+ "Death",
+ "Phlebotinium",
+ "Mana",
+ "Energy",
+ "?????"
+ ]
+
}