mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-27 18:42:44 +00:00
[MIRROR] Hallucination Refactor (#10879)
Co-authored-by: Will <7099514+Willburd@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
committed by
GitHub
parent
b6c2f57c69
commit
2f4ae557ee
8
code/__defines/hallucination.dm
Normal file
8
code/__defines/hallucination.dm
Normal file
@@ -0,0 +1,8 @@
|
||||
#define HALLUCINATION_THRESHOLD 20
|
||||
#define XENOCHIFERAL_THRESHOLD 10
|
||||
|
||||
#define HUD_HALLUCINATION_NONE 0
|
||||
#define HUD_HALLUCINATION_CRIT 1
|
||||
#define HUD_HALLUCINATION_TOXIN 2
|
||||
#define HUD_HALLUCINATION_OXY 3
|
||||
#define HUD_HALLUCINATION_ONFIRE 4
|
||||
@@ -43,9 +43,11 @@ SUBSYSTEM_DEF(motiontracker)
|
||||
if(Rt && At && count)
|
||||
while(count-- > 0)
|
||||
// Place at root turf offset from signal responder's turf using px offsets. So it will show up over visblocking.
|
||||
var/image/motion_echo/E = new /image/motion_echo('icons/effects/effects.dmi', Rt, "motion_echo", OBFUSCATION_LAYER, SOUTH)
|
||||
var/image/client_only/motion_echo/E = new /image/client_only/motion_echo('icons/effects/effects.dmi', Rt, "motion_echo", OBFUSCATION_LAYER, SOUTH)
|
||||
E.place_from_root(At)
|
||||
for(var/datum/weakref/C in clients)
|
||||
for(var/datum/weakref/CW in clients)
|
||||
var/client/C = CW?.resolve()
|
||||
if(C)
|
||||
E.append_client(C)
|
||||
currentrun.Remove(key)
|
||||
expended_echos[key] = data
|
||||
|
||||
@@ -237,196 +237,10 @@
|
||||
if(!owner.stat)
|
||||
owner.emote("twitch")
|
||||
|
||||
|
||||
/datum/component/xenochimera/proc/handle_feral()
|
||||
if(owner.handling_hal) return
|
||||
owner.handling_hal = 1
|
||||
|
||||
if(owner.client && feral >= 10) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway.
|
||||
spawn(rand(200,500)/(feral/10))
|
||||
if(!feral) return //just to avoid fuckery in the event that they un-feral in the time it takes for the spawn to proc
|
||||
var/halpick = rand(1,100)
|
||||
switch(halpick)
|
||||
if(0 to 15) //15% chance
|
||||
//Screwy HUD
|
||||
//to_chat(src, "Screwy HUD")
|
||||
owner.hal_screwyhud = pick(1,2,3,3,4,4)
|
||||
spawn(rand(100,250))
|
||||
owner.hal_screwyhud = 0
|
||||
if(16 to 25) //10% chance
|
||||
//Strange items
|
||||
//to_chat(src, "Traitor Items")
|
||||
if(!owner.halitem)
|
||||
owner.halitem = new
|
||||
var/list/slots_free = list(ui_lhand,ui_rhand)
|
||||
if(owner.l_hand) slots_free -= ui_lhand
|
||||
if(owner.r_hand) slots_free -= ui_rhand
|
||||
if(!owner.belt) slots_free += ui_belt
|
||||
if(!owner.l_store) slots_free += ui_storage1
|
||||
if(!owner.r_store) slots_free += ui_storage2
|
||||
if(slots_free.len)
|
||||
owner.halitem.screen_loc = pick(slots_free)
|
||||
owner.halitem.layer = 50
|
||||
switch(rand(1,6))
|
||||
if(1) //revolver
|
||||
owner.halitem.icon = 'icons/obj/gun.dmi'
|
||||
owner.halitem.icon_state = "revolver"
|
||||
owner.halitem.name = "Revolver"
|
||||
if(2) //c4
|
||||
owner.halitem.icon = 'icons/obj/assemblies.dmi'
|
||||
owner.halitem.icon_state = "plastic-explosive0"
|
||||
owner.halitem.name = "Mysterious Package"
|
||||
if(prob(25))
|
||||
owner.halitem.icon_state = "c4small_1"
|
||||
if(3) //sword
|
||||
owner.halitem.icon = 'icons/obj/weapons.dmi'
|
||||
owner.halitem.icon_state = "sword1"
|
||||
owner.halitem.name = "Sword"
|
||||
if(4) //stun baton
|
||||
owner.halitem.icon = 'icons/obj/weapons.dmi'
|
||||
owner.halitem.icon_state = "stunbaton"
|
||||
owner.halitem.name = "Stun Baton"
|
||||
if(5) //emag
|
||||
owner.halitem.icon = 'icons/obj/card.dmi'
|
||||
owner.halitem.icon_state = "emag"
|
||||
owner.halitem.name = "Cryptographic Sequencer"
|
||||
if(6) //flashbang
|
||||
owner.halitem.icon = 'icons/obj/grenade.dmi'
|
||||
owner.halitem.icon_state = "flashbang1"
|
||||
owner.halitem.name = "Flashbang"
|
||||
if(owner.client) owner.client.screen += owner.halitem
|
||||
spawn(rand(100,250))
|
||||
if(owner.client)
|
||||
owner.client.screen -= owner.halitem
|
||||
owner.halitem = null
|
||||
if(26 to 35) //10% chance
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
if(!owner.halimage)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(owner,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
|
||||
switch(rand(1,3))
|
||||
if(1)
|
||||
//to_chat(src, "Space")
|
||||
owner.halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
|
||||
if(2)
|
||||
//to_chat(src, "Fire")
|
||||
owner.halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
|
||||
if(3)
|
||||
//to_chat(src, "C4")
|
||||
owner.halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
|
||||
|
||||
|
||||
if(owner.client) owner.client.images += owner.halimage
|
||||
spawn(rand(10,50)) //Only seen for a brief moment.
|
||||
if(owner.client) owner.client.images -= owner.halimage
|
||||
owner.halimage = null
|
||||
|
||||
if(36 to 55) //20% chance
|
||||
//Strange audio
|
||||
//to_chat(src, "Strange Audio")
|
||||
switch(rand(1,12))
|
||||
if(1) owner << 'sound/machines/door/old_airlock.ogg'
|
||||
if(2)
|
||||
if(prob(50))owner << 'sound/effects/Explosion1.ogg'
|
||||
else owner << 'sound/effects/Explosion2.ogg'
|
||||
if(3) owner << 'sound/effects/explosionfar.ogg'
|
||||
if(4) owner << 'sound/effects/Glassbr1.ogg'
|
||||
if(5) owner << 'sound/effects/Glassbr2.ogg'
|
||||
if(6) owner << 'sound/effects/Glassbr3.ogg'
|
||||
if(7) owner << 'sound/machines/twobeep.ogg'
|
||||
if(8) owner << 'sound/machines/door/windowdoor.ogg'
|
||||
if(9)
|
||||
//To make it more realistic, I added two gunshots (enough to kill)
|
||||
owner << 'sound/weapons/Gunshot1.ogg'
|
||||
spawn(rand(10,30))
|
||||
owner << 'sound/weapons/Gunshot2.ogg'
|
||||
if(10) owner << 'sound/weapons/smash.ogg'
|
||||
if(11)
|
||||
//Same as above, but with tasers.
|
||||
owner << 'sound/weapons/Taser.ogg'
|
||||
spawn(rand(10,30))
|
||||
owner << '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')
|
||||
owner << pick(creepyasssounds)
|
||||
if(56 to 60) //5% chance
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
if(!owner.halbody)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(owner,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
switch(rand(1,4))
|
||||
if(1)
|
||||
owner.halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER)
|
||||
if(2,3)
|
||||
owner.halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
|
||||
if(4)
|
||||
owner.halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)
|
||||
// if(5)
|
||||
// halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER)
|
||||
|
||||
if(owner.client) owner.client.images += owner.halbody
|
||||
spawn(rand(50,80)) //Only seen for a brief moment.
|
||||
if(owner.client) owner.client.images -= owner.halbody
|
||||
owner.halbody = null
|
||||
if(61 to 85) //25% chance
|
||||
//food
|
||||
if(!owner.halbody)
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(owner,world.view))
|
||||
possible_points += F
|
||||
if(possible_points.len)
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
switch(rand(1,10))
|
||||
if(1)
|
||||
owner.halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER)
|
||||
if(2)
|
||||
owner.halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER)
|
||||
if(3)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER)
|
||||
if(4)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER)
|
||||
if(5)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER)
|
||||
if(6)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER)
|
||||
if(7)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER)
|
||||
if(8)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER)
|
||||
if(9)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER)
|
||||
if(10)
|
||||
owner.halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER)
|
||||
|
||||
if(owner.client) owner.client.images += owner.halbody
|
||||
spawn(rand(50,80)) //Only seen for a brief moment.
|
||||
if(owner.client) owner.client.images -= owner.halbody
|
||||
owner.halbody = null
|
||||
if(86 to 100) //15% chance
|
||||
//hear voices. Could make the voice pick from nearby creatures, but nearby creatures make feral hallucinations rare so don't bother.
|
||||
var/list/hiddenspeakers = list("Someone distant", "A voice nearby","A familiar voice", "An echoing voice", "A cautious voice", "A scared voice", "Someone around the corner", "Someone", "Something", "Something scary", "An urgent voice", "An angry voice")
|
||||
var/list/speakerverbs = list("calls out", "yells", "screams", "exclaims", "shrieks", "shouts", "hisses", "snarls")
|
||||
var/list/spookyphrases = list("It's over here!","Stop it!", "Hunt it down!", "Get it!", "Quick, over here!", "Anyone there?", "Who's there?", "Catch that thing!", "Stop it! Kill it!", "Anyone there?", "Where is it?", "Find it!", "There it is!")
|
||||
to_chat(owner, span_game(span_say(span_name(pick(hiddenspeakers)) + " [pick(speakerverbs)], \"[pick(spookyphrases)]\"")))
|
||||
|
||||
|
||||
owner.handling_hal = 0
|
||||
if(QDELETED(owner) || owner.get_hallucination_component() || !owner.client || feral < XENOCHIFERAL_THRESHOLD)
|
||||
return
|
||||
owner.LoadComponent(/datum/component/hallucinations/xenochimera)
|
||||
|
||||
/obj/screen/xenochimera
|
||||
icon = 'icons/mob/chimerahud.dmi'
|
||||
|
||||
@@ -674,6 +674,7 @@ About the new airlock wires panel:
|
||||
return
|
||||
else if(user.hallucination > 50 && prob(10) && src.operating == 0)
|
||||
to_chat(user, span_danger("You feel a powerful shock course through your body!"))
|
||||
user.playsound_local(get_turf(user), get_sfx("sparks"), vol = 75)
|
||||
user.halloss += 10
|
||||
user.stunned += 10
|
||||
return
|
||||
|
||||
23
code/game/objects/effects/client_only_image.dm
Normal file
23
code/game/objects/effects/client_only_image.dm
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Sending images to clients can cause memory leaks if not handled safely.
|
||||
* This is a wrapper for handling it safely. Mostly used by self deleting effects.
|
||||
*/
|
||||
/image/client_only
|
||||
var/list/clients = list()
|
||||
|
||||
/image/client_only/proc/append_client(var/client/C)
|
||||
C.images += src
|
||||
clients.Add(WEAKREF(C))
|
||||
|
||||
/image/client_only/Destroy(force)
|
||||
. = ..()
|
||||
for(var/datum/weakref/CW in clients)
|
||||
var/client/C = CW?.resolve()
|
||||
if(C)
|
||||
C.images -= src
|
||||
|
||||
// Mostly for motion echos, but someone will probably find another use for it... So parent type gets it instead!
|
||||
/image/client_only/proc/place_from_root(var/turf/At)
|
||||
var/rand_limit = 12
|
||||
pixel_x += ((At.x - loc.x) * 32) + rand(-rand_limit,rand_limit)
|
||||
pixel_y += ((At.y - loc.y) * 32) + rand(-rand_limit,rand_limit)
|
||||
@@ -1,27 +1,8 @@
|
||||
/image/motion_echo
|
||||
/image/client_only/motion_echo
|
||||
plane = PLANE_FULLSCREEN
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
appearance_flags = (RESET_COLOR|PIXEL_SCALE|KEEP_APART)
|
||||
var/list/clients = list()
|
||||
|
||||
/image/motion_echo/New(icon, loc, icon_state, layer, dir)
|
||||
/image/client_only/motion_echo/New(icon, loc, icon_state, layer, dir)
|
||||
. = ..()
|
||||
QDEL_IN(src, 2 SECONDS)
|
||||
|
||||
/image/motion_echo/proc/place_from_root(var/turf/At)
|
||||
var/rand_limit = 12
|
||||
pixel_x += ((At.x - loc.x) * 32) + rand(-rand_limit,rand_limit)
|
||||
pixel_y += ((At.y - loc.y) * 32) + rand(-rand_limit,rand_limit)
|
||||
|
||||
/image/motion_echo/proc/append_client(var/datum/weakref/C)
|
||||
var/client/CW = C?.resolve()
|
||||
if(CW)
|
||||
CW.images += src
|
||||
clients.Add(C)
|
||||
|
||||
/image/motion_echo/Destroy(force)
|
||||
. = ..()
|
||||
for(var/datum/weakref/C in clients)
|
||||
var/client/CW = C?.resolve()
|
||||
if(CW)
|
||||
CW.images -= src
|
||||
|
||||
@@ -8,409 +8,132 @@ 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
|
||||
/datum/component/hallucinations
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE // First come first serve
|
||||
|
||||
VAR_PRIVATE/mob/living/carbon/human/our_human = null
|
||||
VAR_PRIVATE/datum/weakref/halimage
|
||||
VAR_PRIVATE/datum/weakref/halbody
|
||||
VAR_PRIVATE/list/halitem = list() // weakref pair of obj-key, client-value
|
||||
|
||||
VAR_PRIVATE/hal_crit = FALSE
|
||||
VAR_PRIVATE/hal_screwyhud = HUD_HALLUCINATION_NONE
|
||||
|
||||
/datum/component/hallucinations/Initialize()
|
||||
if(!ishuman(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
our_human = parent
|
||||
make_timer()
|
||||
|
||||
/datum/component/hallucinations/Destroy(force)
|
||||
if(halitem.len)
|
||||
remove_hallucination_item()
|
||||
our_human = null
|
||||
. = ..()
|
||||
|
||||
/datum/component/hallucinations/proc/make_timer()
|
||||
PROTECTED_PROC(TRUE)
|
||||
addtimer(CALLBACK(src, PROC_REF(trigger)), ((rand(20,50) SECONDS) / (min(our_human.hallucination,100)/25)), TIMER_DELETE_ME)
|
||||
|
||||
/datum/component/hallucinations/proc/get_fakecrit()
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
return hal_crit
|
||||
|
||||
/datum/component/hallucinations/proc/get_hud_state()
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
return hal_screwyhud
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Traditional hallucinations
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/mob/living/carbon/proc/handle_hallucinations()
|
||||
if(handling_hal) return
|
||||
handling_hal = 1
|
||||
while(client && hallucination > 20)
|
||||
sleep(rand(200,500)/(hallucination/25))
|
||||
if(get_hallucination_component() || !client)
|
||||
return
|
||||
LoadComponent(/datum/component/hallucinations)
|
||||
|
||||
/mob/living/carbon/proc/get_hallucination_component()
|
||||
RETURN_TYPE(/datum/component/hallucinations)
|
||||
return GetComponent(/datum/component/hallucinations)
|
||||
|
||||
/datum/component/hallucinations/proc/trigger()
|
||||
PROTECTED_PROC(TRUE)
|
||||
if(QDELETED(our_human))
|
||||
qdel(src)
|
||||
return
|
||||
if(!our_human.client)
|
||||
qdel(src)
|
||||
return
|
||||
if(our_human.hallucination < HALLUCINATION_THRESHOLD)
|
||||
qdel(src)
|
||||
return
|
||||
handle_hallucinating()
|
||||
make_timer()
|
||||
|
||||
/datum/component/hallucinations/proc/handle_hallucinating()
|
||||
PROTECTED_PROC(TRUE)
|
||||
var/halpick = rand(1,100)
|
||||
switch(halpick)
|
||||
if(0 to 15)
|
||||
//Screwy HUD
|
||||
//to_chat(src, "Screwy HUD")
|
||||
hal_screwyhud = pick(1,2,3,3,4,4)
|
||||
spawn(rand(100,250))
|
||||
hal_screwyhud = 0
|
||||
event_hudscrew()
|
||||
if(16 to 25)
|
||||
//Strange items
|
||||
//to_chat(src, "Traitor 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(ishuman(src))
|
||||
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.hud_layerise()
|
||||
switch(rand(1,6))
|
||||
if(1) //revolver
|
||||
halitem.icon = 'icons/obj/gun.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
|
||||
event_fake_item()
|
||||
if(26 to 40)
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
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)
|
||||
//to_chat(src, "Space")
|
||||
halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
|
||||
if(2)
|
||||
//to_chat(src, "Fire")
|
||||
halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
|
||||
if(3)
|
||||
//to_chat(src, "C4")
|
||||
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
|
||||
|
||||
|
||||
event_flash_environmental_threats()
|
||||
if(41 to 65)
|
||||
//Strange audio
|
||||
//to_chat(src, "Strange Audio")
|
||||
switch(rand(1,12))
|
||||
if(1) src << 'sound/machines/door/old_airlock.ogg'
|
||||
if(2)
|
||||
if(prob(50))src << 'sound/effects/Explosion1.ogg'
|
||||
else src << 'sound/effects/Explosion2.ogg'
|
||||
if(3) src << 'sound/effects/explosionfar.ogg'
|
||||
if(4) src << 'sound/effects/Glassbr1.ogg'
|
||||
if(5) src << 'sound/effects/Glassbr2.ogg'
|
||||
if(6) src << 'sound/effects/Glassbr3.ogg'
|
||||
if(7) src << 'sound/machines/twobeep.ogg'
|
||||
if(8) src << 'sound/machines/door/windowdoor.ogg'
|
||||
if(9)
|
||||
//To make it more realistic, I added two gunshots (enough to kill)
|
||||
src << 'sound/weapons/Gunshot1.ogg'
|
||||
spawn(rand(10,30))
|
||||
src << 'sound/weapons/Gunshot2.ogg'
|
||||
if(10) src << 'sound/weapons/smash.ogg'
|
||||
if(11)
|
||||
//Same as above, but with tasers.
|
||||
src << 'sound/weapons/Taser.ogg'
|
||||
spawn(rand(10,30))
|
||||
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')
|
||||
src << pick(creepyasssounds)
|
||||
event_strange_sound()
|
||||
if(66 to 70)
|
||||
//Flashes of danger
|
||||
//to_chat(src, "Danger Flash")
|
||||
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/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(prob(20) && our_human.nutrition < 100)
|
||||
event_hunger() // Hungi, meant for xenochi but this is too funny to pass up
|
||||
else
|
||||
event_flash_monsters()
|
||||
if(71 to 72)
|
||||
//Fake death
|
||||
// src.sleeping_willingly = 1
|
||||
SetSleeping(20)
|
||||
hal_crit = 1
|
||||
hal_screwyhud = 1
|
||||
spawn(rand(50,100))
|
||||
// src.sleeping_willingly = 0
|
||||
SetSleeping(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 Site Manager 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='byond://?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 (ishuman(M) || isAI(M))
|
||||
if(M.hallucination < 15)
|
||||
return 1
|
||||
return 0*/
|
||||
|
||||
/* //ChompREMOVE fake_attacker - EXTREME image qdel usage. Look at the attack_loop and updateimage procs and weep.
|
||||
/obj/effect/fake_attacker
|
||||
icon = null
|
||||
icon_state = null
|
||||
name = ""
|
||||
desc = ""
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
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
|
||||
|
||||
/obj/effect/fake_attacker/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_bolddanger("[my_target] flails around wildly."))
|
||||
my_target.show_message(span_bolddanger("[src] has been attacked by [my_target] "), 1) //Lazy.
|
||||
|
||||
src.health -= P.force
|
||||
event_sleeping()
|
||||
if(73 to 75) // If you don't want hallucination beatdowns, comment this out
|
||||
event_attacker()
|
||||
if(76 to 80)
|
||||
event_painmessage()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Xenochimera hallucinations
|
||||
// Unlike normal hallucinations this one is triggered from handle_feral randomly.
|
||||
// So it destroys itself after it triggers, freeing up space for the next run of it.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/datum/component/hallucinations/xenochimera/make_timer()
|
||||
var/datum/component/xenochimera/XC = our_human.GetComponent(/datum/component/xenochimera)
|
||||
var/F = XC ? (XC.feral / 10) : 1
|
||||
addtimer(CALLBACK(src, PROC_REF(trigger)), ((rand(20,50) SECONDS) / F), TIMER_DELETE_ME)
|
||||
|
||||
/datum/component/hallucinations/xenochimera/trigger()
|
||||
if(QDELETED(our_human))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/fake_attacker/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_bolddanger("[my_target] stumbles around."))
|
||||
|
||||
/obj/effect/fake_attacker/Initialize(mapload)
|
||||
. = ..()
|
||||
QDEL_IN(src, 30 SECONDS)
|
||||
step_away(src,my_target,2)
|
||||
addtimer(CALLBACK(src, PROC_REF(attack_loop)), rand(5, 10), TIMER_DELETE_ME)
|
||||
|
||||
/obj/effect/fake_attacker/Destroy()
|
||||
if(my_target)
|
||||
my_target.hallucinations -= src
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/fake_attacker/proc/updateimage()
|
||||
// qdel(src.currentimage)
|
||||
|
||||
|
||||
if(src.dir == NORTH)
|
||||
qdel(src.currentimage)
|
||||
src.currentimage = new /image(up,src)
|
||||
else if(src.dir == SOUTH)
|
||||
qdel(src.currentimage)
|
||||
src.currentimage = new /image(down,src)
|
||||
else if(src.dir == EAST)
|
||||
qdel(src.currentimage)
|
||||
src.currentimage = new /image(right,src)
|
||||
else if(src.dir == WEST)
|
||||
qdel(src.currentimage)
|
||||
src.currentimage = new /image(left,src)
|
||||
my_target << currentimage
|
||||
|
||||
|
||||
/obj/effect/fake_attacker/proc/attack_loop()
|
||||
if(src.health < 0)
|
||||
collapse()
|
||||
addtimer(CALLBACK(src, PROC_REF(attack_loop)), rand(5, 10), TIMER_DELETE_ME)
|
||||
if(!our_human.client)
|
||||
qdel(src)
|
||||
return
|
||||
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_bolddanger("[my_target] has been attacked with [weapon_name] by [src.name]!"), 1)
|
||||
my_target.halloss += 8
|
||||
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_bolddanger("[src.name] has punched [my_target]!"), 1)
|
||||
my_target.halloss += 4
|
||||
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)
|
||||
addtimer(CALLBACK(src, PROC_REF(attack_loop)), rand(5, 10), TIMER_DELETE_ME)
|
||||
|
||||
/obj/effect/fake_attacker/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, 30 SECONDS)
|
||||
|
||||
var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_magazine/s357,\
|
||||
/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/chameleon, /obj/item/card/emag,\
|
||||
/obj/item/storage/toolbox/syndicate, /obj/item/aiModule,\
|
||||
/obj/item/radio/headset/syndicate, /obj/item/plastique,\
|
||||
/obj/item/powersink, /obj/item/storage/box/syndie_kit,\
|
||||
/obj/item/toy/syndicateballoon, /obj/item/gun/energy/captain,\
|
||||
/obj/item/hand_tele, /obj/item/rcd, /obj/item/tank/jetpack,\
|
||||
/obj/item/clothing/under/rank/captain, /obj/item/aicard,\
|
||||
/obj/item/clothing/shoes/magboots, /obj/item/areaeditor/blueprints, /obj/item/disk/nuclear,\
|
||||
/obj/item/clothing/suit/space/void, /obj/item/tank)
|
||||
|
||||
/proc/fake_attack(var/mob/living/target)
|
||||
var/list/possible_clones = new/list()
|
||||
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
|
||||
possible_clones += H
|
||||
// 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(!possible_clones.len)
|
||||
return
|
||||
clone = pick(possible_clones)
|
||||
if(!clone)
|
||||
var/datum/component/xenochimera/XC = our_human.GetComponent(/datum/component/xenochimera)
|
||||
if(!XC || XC.feral < XENOCHIFERAL_THRESHOLD)
|
||||
qdel(src)
|
||||
return
|
||||
handle_hallucinating()
|
||||
QDEL_IN(src,rand(3,9)SECONDS)
|
||||
|
||||
//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.base = new /icon(clone.stand_icon)
|
||||
// F.currentimage = new /image(clone)
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
F.left = new /icon(clone.stand_icon,dir=WEST)
|
||||
for(var/icon/i in clone.overlays)
|
||||
F.left.Blend(i)
|
||||
F.up = new /icon(clone.stand_icon,dir=NORTH)
|
||||
for(var/icon/i in clone.overlays)
|
||||
F.up.Blend(i)
|
||||
F.down = new /icon(clone.stand_icon,dir=SOUTH)
|
||||
for(var/icon/i in clone.overlays)
|
||||
F.down.Blend(i)
|
||||
F.right = new /icon(clone.stand_icon,dir=EAST)
|
||||
for(var/icon/i in clone.overlays)
|
||||
F.right.Blend(i)
|
||||
|
||||
target << F.up
|
||||
*/
|
||||
|
||||
F.updateimage()
|
||||
*/ //ChompREMOVE End
|
||||
/datum/component/hallucinations/xenochimera/handle_hallucinating()
|
||||
var/halpick = rand(1,100)
|
||||
switch(halpick)
|
||||
if(0 to 15) //15% chance
|
||||
//Screwy HUD
|
||||
event_hudscrew()
|
||||
if(16 to 25) //10% chance
|
||||
event_fake_item()
|
||||
if(26 to 35) //10% chance
|
||||
event_flash_environmental_threats()
|
||||
if(36 to 55) //20% chance
|
||||
event_strange_sound()
|
||||
if(56 to 60) //5% chance
|
||||
event_flash_monsters()
|
||||
if(61 to 85) //25% chance
|
||||
event_hunger()
|
||||
if(86 to 100) //15% chance
|
||||
event_hear_voices()
|
||||
|
||||
218
code/modules/flufftext/fake_attacker.dm
Normal file
218
code/modules/flufftext/fake_attacker.dm
Normal file
@@ -0,0 +1,218 @@
|
||||
/obj/effect/fake_attacker // I did want to use /image/client_only but this needs to be somewhat more complex
|
||||
name = ""
|
||||
desc = ""
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
opacity = 0
|
||||
VAR_PRIVATE/list/clients = list()
|
||||
VAR_PRIVATE/list/image/dir_images = list()
|
||||
|
||||
/obj/effect/fake_attacker/process()
|
||||
. = ..()
|
||||
// Passive cleanup
|
||||
for(var/datum/weakref/C in clients)
|
||||
var/client/CW = C?.resolve()
|
||||
if(isnull(CW))
|
||||
clients.Remove(C)
|
||||
if(!clients.len)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/fake_attacker/set_dir(newdir)
|
||||
if(!(newdir in GLOB.cardinal))
|
||||
newdir &= ~(EAST|WEST) // Don't allow diagonals, prefer north/south
|
||||
if(!newdir)
|
||||
newdir = SOUTH
|
||||
var/updatesprite = (dir != newdir)
|
||||
. = ..()
|
||||
if(updatesprite)
|
||||
for(var/datum/weakref/C in clients)
|
||||
var/client/CW = C?.resolve()
|
||||
clear_images_from_client(CW)
|
||||
assign_image_to_client(CW)
|
||||
|
||||
/obj/effect/fake_attacker/Moved(atom/old_loc, direction, forced, movetime)
|
||||
. = ..()
|
||||
var/turf_move = isturf(loc) && isturf(old_loc)
|
||||
for(var/img in dir_images)
|
||||
var/image/G = dir_images[img]
|
||||
G.loc = loc
|
||||
if(turf_move)
|
||||
var/MT = 0.7 SECONDS
|
||||
G.pixel_x = (old_loc.x - loc.x) * WORLD_ICON_SIZE
|
||||
G.pixel_y = (old_loc.y - loc.y) * WORLD_ICON_SIZE
|
||||
animate(G, pixel_x = 0, time = MT, flags = ANIMATION_PARALLEL)
|
||||
animate(G, pixel_y = 0, time = MT, flags = ANIMATION_PARALLEL)
|
||||
|
||||
/obj/effect/fake_attacker/Destroy(force)
|
||||
. = ..()
|
||||
clear_every_clients_images()
|
||||
qdel_all_images()
|
||||
|
||||
/obj/effect/fake_attacker/proc/create_images_from(var/atom/clone)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
dir_images["[NORTH]"] = image(clone,dir = NORTH)
|
||||
dir_images["[SOUTH]"] = image(clone,dir = SOUTH)
|
||||
dir_images["[EAST]"] = image(clone,dir = EAST)
|
||||
dir_images["[WEST]"] = image(clone,dir = WEST)
|
||||
for(var/img in dir_images)
|
||||
var/image/G = dir_images[img]
|
||||
G.layer = clone.layer
|
||||
G.plane = clone.plane
|
||||
G.appearance_flags = clone.appearance_flags
|
||||
G.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
G.loc = loc
|
||||
|
||||
/obj/effect/fake_attacker/proc/append_client(var/client/C)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
clients.Add(WEAKREF(C))
|
||||
assign_image_to_client(C)
|
||||
|
||||
/obj/effect/fake_attacker/proc/assign_image_to_client(var/client/C)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
if(!C)
|
||||
return
|
||||
if(!dir_images.len)
|
||||
return
|
||||
var/image/I = dir_images["[dir]"]
|
||||
if(I)
|
||||
C.images += I
|
||||
|
||||
/obj/effect/fake_attacker/proc/clear_every_clients_images()
|
||||
for(var/datum/weakref/C in clients)
|
||||
clear_images_from_client(C?.resolve())
|
||||
|
||||
/obj/effect/fake_attacker/proc/clear_images_from_client(var/client/C)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
if(!C)
|
||||
return
|
||||
if(!dir_images.len)
|
||||
return
|
||||
for(var/img in dir_images)
|
||||
C.images -= dir_images[img]
|
||||
|
||||
/obj/effect/fake_attacker/proc/qdel_all_images()
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
for(var/img in dir_images)
|
||||
qdel_null(dir_images[img])
|
||||
dir_images.Cut()
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Hallucination attackers with AI behaviors
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/mob/proc/create_hallucination_attacker(var/turf/T = null,var/mob/living/carbon/human/clone = null, var/forced_type = null)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
if(!client)
|
||||
return null
|
||||
|
||||
if(!clone)
|
||||
// Get a randomized clone from the living mob's list, must be standing
|
||||
var/list/possible_clones = new/list()
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
if(H.stat || H.lying)
|
||||
continue
|
||||
possible_clones += H
|
||||
if(!possible_clones.len)
|
||||
return null
|
||||
clone = pick(possible_clones)
|
||||
if(!clone)
|
||||
return null
|
||||
|
||||
if(!T)
|
||||
// Get the target's turf, then make some random steps to get away from them, respecting walls
|
||||
T = get_turf(clone)
|
||||
var/turf/CT = T
|
||||
for(var/i = 0 to 8)
|
||||
var/Cdir = pick(GLOB.cardinal)
|
||||
if(prob(30))
|
||||
Cdir = clone.dir // Results in hallucinations somewhat being in front of you
|
||||
var/turf/NT = get_step(CT,Cdir)
|
||||
if(!NT.density)
|
||||
CT = NT
|
||||
T = CT
|
||||
|
||||
if(!forced_type)
|
||||
// Picking from all available options
|
||||
var/list/get_types = subtypesof(/obj/effect/fake_attacker/human)
|
||||
forced_type = pick(get_types)
|
||||
// Finally! After a thousand years I'm finally free to conquer EARTH!
|
||||
return new forced_type(T,src,clone)
|
||||
|
||||
/obj/effect/fake_attacker/human
|
||||
VAR_PROTECTED/datum/weakref/target = null
|
||||
var/requires_hallucinating = TRUE // Mob will qdel if the target is not hallucinating if this is true
|
||||
|
||||
/obj/effect/fake_attacker/human/Initialize(mapload,var/mob/targeting_mob,var/atom/clone_appearance_from)
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
set_target(targeting_mob)
|
||||
create_images_from(clone_appearance_from)
|
||||
append_client(targeting_mob.client)
|
||||
name = clone_appearance_from.name
|
||||
// Usually we want to face our target for maximum spooky effect
|
||||
set_dir(get_dir(src,targeting_mob))
|
||||
|
||||
/obj/effect/fake_attacker/human/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/fake_attacker/human/process()
|
||||
// check if valid
|
||||
var/mob/living/M = target?.resolve()
|
||||
if(!M)
|
||||
qdel(src)
|
||||
return null
|
||||
if(requires_hallucinating)
|
||||
if(!ishuman(M))
|
||||
qdel(src)
|
||||
return null
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!H.hallucination)
|
||||
qdel(src)
|
||||
return null
|
||||
|
||||
return M
|
||||
|
||||
/obj/effect/fake_attacker/human/proc/set_target(var/mob/M)
|
||||
target = WEAKREF(M)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Attacker: Performs hostile shoves and attacks
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/effect/fake_attacker/human/attacker/process()
|
||||
var/mob/living/M = ..()
|
||||
|
||||
if(get_dist(src,M) > 1)
|
||||
step_towards(src,M)
|
||||
|
||||
else if(prob(15))
|
||||
M << sound(pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'))
|
||||
M.show_message(span_bolddanger("\The [src] has punched \the [M]!"), 1)
|
||||
M.halloss += 4
|
||||
|
||||
if(prob(15))
|
||||
step_away(src,M)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fleeing: Runs away when you get close
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/effect/fake_attacker/human/fleeing
|
||||
VAR_PRIVATE/flee = FALSE
|
||||
|
||||
/obj/effect/fake_attacker/human/fleeing/process()
|
||||
var/mob/living/M = ..()
|
||||
set_dir(get_dir(src,M))
|
||||
|
||||
if(get_dist(src,M) < 6 || flee)
|
||||
flee = TRUE
|
||||
step_away(src,M)
|
||||
|
||||
if(get_dist(src,M) > 10 || get_dist(src,M) < 2 || (flee && prob(10)))
|
||||
target = null
|
||||
qdel(src)
|
||||
302
code/modules/flufftext/hallucination_events.dm
Normal file
302
code/modules/flufftext/hallucination_events.dm
Normal file
@@ -0,0 +1,302 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Hallucination events
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/datum/component/hallucinations/proc/event_hudscrew()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//Screwy HUD
|
||||
//to_chat(our_human, "Screwy HUD")
|
||||
hal_screwyhud = pick(list(
|
||||
HUD_HALLUCINATION_CRIT,
|
||||
HUD_HALLUCINATION_TOXIN,
|
||||
HUD_HALLUCINATION_OXY,
|
||||
HUD_HALLUCINATION_ONFIRE
|
||||
))
|
||||
VARSET_IN(src, hal_screwyhud, HUD_HALLUCINATION_NONE, rand(15,35) SECONDS)
|
||||
|
||||
/datum/component/hallucinations/proc/event_painmessage()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//Fake pain messages
|
||||
//to_chat(our_human, "fake messages")
|
||||
var/list/pain_message = list("The inside of your head hurts...",
|
||||
"Your stomach hurts.",
|
||||
"You feel sick.",
|
||||
"Your upper body hurts.",
|
||||
"Your head hurts.",
|
||||
"Your arm hurts.",
|
||||
"Your leg hurts.",
|
||||
"Your lower body hurts.",
|
||||
"Your foot hurts.",
|
||||
"Your hand hurts.",
|
||||
"The pain is excruciating!",
|
||||
"Your whole body is going numb!",
|
||||
"You feel like you could die any moment now!",
|
||||
"Please, just end the pain!",
|
||||
"You feel a sudden pain across your body.",
|
||||
"You cringe as a violent pain takes over your body.",
|
||||
"It feels like your body is eating itself inside out.",
|
||||
"IT HURTS.",
|
||||
"Your body feels as if it's trying to rip itself open..."
|
||||
)
|
||||
if(prob(20) && our_human.jitteriness < 50)
|
||||
our_human.make_jittery(120)
|
||||
to_chat(our_human, span_danger(pick(pain_message)))
|
||||
|
||||
/datum/component/hallucinations/proc/event_fake_item()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//Strange items
|
||||
//to_chat(our_human, "Traitor Items")
|
||||
if(halitem.len)
|
||||
return
|
||||
|
||||
var/list/slots_free = list(ui_lhand,ui_rhand)
|
||||
if(our_human.l_hand)
|
||||
slots_free -= ui_lhand
|
||||
if(our_human.r_hand)
|
||||
slots_free -= ui_rhand
|
||||
if(!our_human.belt)
|
||||
slots_free += ui_belt
|
||||
if(!our_human.l_store)
|
||||
slots_free += ui_storage1
|
||||
if(!our_human.r_store)
|
||||
slots_free += ui_storage2
|
||||
|
||||
if(!slots_free.len)
|
||||
return
|
||||
|
||||
var/obj/CI = new()
|
||||
CI.screen_loc = pick(slots_free)
|
||||
CI.hud_layerise()
|
||||
switch(rand(1,6))
|
||||
if(1) //revolver
|
||||
CI.icon = 'icons/obj/gun.dmi'
|
||||
CI.icon_state = "revolver"
|
||||
CI.name = "Revolver"
|
||||
if(2) //c4
|
||||
CI.icon = 'icons/obj/assemblies.dmi'
|
||||
CI.icon_state = "plastic-explosive0"
|
||||
CI.name = "Mysterious Package"
|
||||
if(prob(25))
|
||||
CI.icon_state = "c4small_1"
|
||||
if(3) //sword
|
||||
CI.icon = 'icons/obj/weapons.dmi'
|
||||
CI.icon_state = "longsword"
|
||||
CI.name = "Sword"
|
||||
if(4) //stun baton
|
||||
CI.icon = 'icons/obj/weapons.dmi'
|
||||
CI.icon_state = "stunbaton"
|
||||
CI.name = "Stun Baton"
|
||||
if(5) //emag
|
||||
CI.icon = 'icons/obj/card.dmi'
|
||||
CI.icon_state = "emag"
|
||||
CI.name = "Cryptographic Sequencer"
|
||||
if(6) //flashbang
|
||||
CI.icon = 'icons/obj/grenade.dmi'
|
||||
CI.icon_state = "flashbang1"
|
||||
CI.name = "Flashbang"
|
||||
halitem[WEAKREF(CI)] = WEAKREF(our_human.client)
|
||||
our_human.client.screen += CI
|
||||
addtimer(CALLBACK(src, PROC_REF(remove_hallucination_item)), rand(10,25) SECONDS, TIMER_DELETE_ME)
|
||||
|
||||
/datum/component/hallucinations/proc/remove_hallucination_item()
|
||||
// I can't manage this with /image/client_only due to screenloc, so key-value weakref pair it is! Called on both timer and destroying this component.
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
var/datum/weakref/first = halitem[1]
|
||||
var/obj/itm = first?.resolve()
|
||||
var/datum/weakref/CW = halitem[first]
|
||||
var/client/C = CW?.resolve()
|
||||
C.screen -= itm
|
||||
qdel(itm)
|
||||
halitem.Cut()
|
||||
|
||||
/datum/component/hallucinations/proc/event_strange_sound()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
|
||||
//Strange audio
|
||||
var/send_sound
|
||||
switch(rand(1,12))
|
||||
if(1)
|
||||
send_sound = 'sound/machines/door/old_airlock.ogg'
|
||||
if(2)
|
||||
if(prob(50))
|
||||
send_sound = 'sound/effects/Explosion1.ogg'
|
||||
else
|
||||
send_sound = 'sound/effects/Explosion2.ogg'
|
||||
if(3)
|
||||
send_sound = 'sound/effects/explosionfar.ogg'
|
||||
if(4)
|
||||
send_sound = 'sound/effects/Glassbr1.ogg'
|
||||
if(5)
|
||||
send_sound = 'sound/effects/Glassbr2.ogg'
|
||||
if(6)
|
||||
send_sound = 'sound/effects/Glassbr3.ogg'
|
||||
if(7)
|
||||
send_sound = 'sound/machines/twobeep.ogg'
|
||||
if(8)
|
||||
send_sound = 'sound/machines/door/windowdoor.ogg'
|
||||
if(9)
|
||||
//To make it more realistic, I added two gunshots (enough to kill)
|
||||
send_sound = 'sound/weapons/Gunshot1.ogg'
|
||||
addtimer(CALLBACK(src, PROC_REF(secondary_sound), 'sound/weapons/Gunshot2.ogg'), rand(1,3) SECONDS, TIMER_DELETE_ME)
|
||||
if(10)
|
||||
send_sound = 'sound/weapons/smash.ogg'
|
||||
if(11)
|
||||
//Same as above, but with tasers.
|
||||
send_sound = 'sound/weapons/Taser.ogg'
|
||||
addtimer(CALLBACK(src, PROC_REF(secondary_sound), 'sound/weapons/Taser.ogg'), rand(1,3) SECONDS, TIMER_DELETE_ME)
|
||||
//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')
|
||||
send_sound = pick(creepyasssounds)
|
||||
|
||||
our_human.playsound_local(get_turf(our_human), send_sound, vol = 75, channel = CHANNEL_AMBIENCE_FORCED)
|
||||
|
||||
/datum/component/hallucinations/proc/secondary_sound(var/sound_path)
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
our_human.playsound_local(get_turf(our_human), sound_path, vol = 75, channel = CHANNEL_AMBIENCE_FORCED)
|
||||
|
||||
/datum/component/hallucinations/proc/event_flash_environmental_threats()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//Flashes of danger
|
||||
//to_chat(our_human, "Danger Flash")
|
||||
if(halimage?.resolve())
|
||||
return
|
||||
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(our_human,world.view))
|
||||
possible_points += F
|
||||
if(!possible_points.len)
|
||||
return
|
||||
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
var/image/client_only/CI
|
||||
switch(rand(1,3))
|
||||
if(1)
|
||||
//to_chat(our_human, "Space")
|
||||
CI = new('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
|
||||
if(2)
|
||||
//to_chat(our_human, "Fire")
|
||||
CI = new('icons/effects/fire.dmi',target,"1",TURF_LAYER)
|
||||
if(3)
|
||||
//to_chat(our_human, "C4")
|
||||
CI = new('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
|
||||
halimage = WEAKREF(CI)
|
||||
CI.append_client(our_human.client)
|
||||
QDEL_IN(CI, rand(1,5) SECONDS) //Only seen for a brief moment.
|
||||
|
||||
/datum/component/hallucinations/proc/event_flash_monsters()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//Flashes of danger
|
||||
//to_chat(our_human, "Danger Flash")
|
||||
if(halbody?.resolve())
|
||||
return
|
||||
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(our_human,world.view))
|
||||
possible_points += F
|
||||
if(!possible_points.len)
|
||||
return
|
||||
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
var/image/client_only/CI
|
||||
switch(rand(1,4))
|
||||
if(1)
|
||||
CI = new('icons/mob/human.dmi',target,"husk_l",TURF_LAYER)
|
||||
if(2,3)
|
||||
CI = new('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
|
||||
if(4)
|
||||
CI = new('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)
|
||||
// if(5)
|
||||
// CI = new('xcomalien.dmi',target,"chryssalid",TURF_LAYER)
|
||||
halbody = WEAKREF(CI)
|
||||
CI.append_client(our_human.client)
|
||||
QDEL_IN(CI, rand(5,8) SECONDS) //Only seen for a brief moment.
|
||||
|
||||
/datum/component/hallucinations/proc/event_sleeping()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//Fake death
|
||||
//to_chat(our_human, "fake death")
|
||||
our_human.SetSleeping(20)
|
||||
hal_crit = TRUE
|
||||
hal_screwyhud = HUD_HALLUCINATION_CRIT
|
||||
addtimer(CALLBACK(src, PROC_REF(reset_hallucination_sleeping)), rand(5,10) SECONDS, TIMER_DELETE_ME)
|
||||
|
||||
/datum/component/hallucinations/proc/reset_hallucination_sleeping()
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
our_human.SetSleeping(0)
|
||||
hal_crit = FALSE
|
||||
hal_screwyhud = HUD_HALLUCINATION_NONE
|
||||
|
||||
/datum/component/hallucinations/proc/event_attacker()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
var/attacker = our_human.create_hallucination_attacker(forced_type = /obj/effect/fake_attacker/human/attacker) // Currently just uses the attacker type for now, remove argument to use any other subtype
|
||||
if(attacker)
|
||||
QDEL_IN(attacker, rand(25,30) SECONDS)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Xenochimera feral events
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/datum/component/hallucinations/proc/event_hunger()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//food
|
||||
if(halbody?.resolve())
|
||||
return
|
||||
|
||||
var/list/possible_points = list()
|
||||
for(var/turf/simulated/floor/F in view(our_human,world.view))
|
||||
possible_points += F
|
||||
if(!possible_points.len)
|
||||
return
|
||||
|
||||
var/turf/simulated/floor/target = pick(possible_points)
|
||||
var/image/client_only/CI
|
||||
switch(rand(1,10))
|
||||
if(1)
|
||||
CI = new('icons/mob/animal.dmi',target,"cow",TURF_LAYER)
|
||||
if(2)
|
||||
CI = new('icons/mob/animal.dmi',target,"chicken",TURF_LAYER)
|
||||
if(3)
|
||||
CI = new('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER)
|
||||
if(4)
|
||||
CI = new('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER)
|
||||
if(5)
|
||||
CI = new('icons/obj/food.dmi',target,"sausage",TURF_LAYER)
|
||||
if(6)
|
||||
CI = new('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER)
|
||||
if(7)
|
||||
CI = new('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER)
|
||||
if(8)
|
||||
CI = new('icons/obj/food.dmi',target,"meat",TURF_LAYER)
|
||||
if(9)
|
||||
CI = new('icons/obj/food.dmi',target,"meatstake",TURF_LAYER)
|
||||
if(10)
|
||||
CI = new('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER)
|
||||
|
||||
halbody = WEAKREF(CI)
|
||||
CI.append_client(our_human.client)
|
||||
QDEL_IN(CI, rand(5,8) SECONDS) //Only seen for a brief moment.
|
||||
|
||||
/datum/component/hallucinations/proc/event_hear_voices()
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
//hear voices. Could make the voice pick from nearby creatures, but nearby creatures make feral hallucinations rare so don't bother.
|
||||
var/list/hiddenspeakers = list("Someone distant", "A voice nearby","A familiar voice", "An echoing voice", "A cautious voice", "A scared voice", "Someone around the corner", "Someone", "Something", "Something scary", "An urgent voice", "An angry voice")
|
||||
var/list/speakerverbs = list("calls out", "yells", "screams", "exclaims", "shrieks", "shouts", "hisses", "snarls")
|
||||
var/list/spookyphrases = list("It's over here!","Stop it!", "Hunt it down!", "Get it!", "Quick, over here!", "Anyone there?", "Who's there?", "Catch that thing!", "Stop it! Kill it!", "Anyone there?", "Where is it?", "Find it!", "There it is!")
|
||||
to_chat(our_human, span_game(span_say(span_name(pick(hiddenspeakers)) + " [pick(speakerverbs)], \"[pick(spookyphrases)]\"")))
|
||||
@@ -722,6 +722,11 @@
|
||||
spawn(0) emote(pick("giggle", "laugh"))
|
||||
breath.adjust_gas(GAS_N2O, -breath.gas[GAS_N2O]/6, update = 0) //update after
|
||||
|
||||
if(get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_OXY)
|
||||
throw_alert("oxy", /obj/screen/alert/not_enough_atmos)
|
||||
else if(get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_TOXIN)
|
||||
throw_alert("tox_in_air", /obj/screen/alert/tox_in_air)
|
||||
|
||||
// Were we able to breathe?
|
||||
if (failed_inhale || failed_exhale)
|
||||
failed_last_breath = 1
|
||||
@@ -1249,20 +1254,15 @@
|
||||
Paralyse(3)
|
||||
|
||||
if(hallucination)
|
||||
if(hallucination >= 20 && !(species.flags & (NO_POISON|IS_PLANT|NO_HALLUCINATION)) )
|
||||
if(!handling_hal)
|
||||
spawn handle_hallucinations() //The not boring kind!
|
||||
if(hallucination >= HALLUCINATION_THRESHOLD && !(species.flags & (NO_POISON|IS_PLANT|NO_HALLUCINATION)) )
|
||||
handle_hallucinations()
|
||||
/* Stop spinning the view, it breaks too much.
|
||||
if(client && prob(5))
|
||||
client.dir = pick(2,4,8)
|
||||
spawn(rand(20,50))
|
||||
client.dir = 1
|
||||
*/
|
||||
|
||||
hallucination = max(0, hallucination - 2)
|
||||
else
|
||||
for(var/atom/a in hallucinations)
|
||||
qdel(a)
|
||||
|
||||
//Brain damage from Oxyloss
|
||||
if(should_have_organ(O_BRAIN))
|
||||
@@ -1326,7 +1326,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)
|
||||
handle_sleeping()
|
||||
if( prob(2) && health && !hal_crit && client )
|
||||
if( prob(2) && health && !get_hallucination_component()?.get_fakecrit() && client )
|
||||
spawn(0)
|
||||
emote("snore")
|
||||
//CONSCIOUS
|
||||
@@ -1554,10 +1554,12 @@
|
||||
health_images += E.get_damage_hud_image(limb_trauma_val)
|
||||
|
||||
// Apply a fire overlay if we're burning.
|
||||
if(on_fire)
|
||||
if(on_fire || get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_ONFIRE)
|
||||
health_images += image('icons/mob/OnFire.dmi',"[get_fire_icon_state()]")
|
||||
|
||||
// Show a general pain/crit indicator if needed.
|
||||
if(get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_CRIT)
|
||||
trauma_val = 2
|
||||
if(trauma_val)
|
||||
if(!(species.flags & NO_PAIN))
|
||||
if(trauma_val > 0.7)
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
var/max_nutrition = MAX_NUTRITION
|
||||
|
||||
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.
|
||||
var/base_attack_cooldown = DEFAULT_ATTACK_COOLDOWN
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#include "code\__defines\fonts.dm"
|
||||
#include "code\__defines\footsteps.dm"
|
||||
#include "code\__defines\gamemode.dm"
|
||||
#include "code\__defines\hallucination.dm"
|
||||
#include "code\__defines\holder.dm"
|
||||
#include "code\__defines\holomap.dm"
|
||||
#include "code\__defines\hoses.dm"
|
||||
@@ -1339,6 +1340,7 @@
|
||||
#include "code\game\objects\effects\blockers_yw.dm"
|
||||
#include "code\game\objects\effects\bluespace_spawner_ch.dm"
|
||||
#include "code\game\objects\effects\bump_teleporter.dm"
|
||||
#include "code\game\objects\effects\client_only_image.dm"
|
||||
#include "code\game\objects\effects\confetti_vr.dm"
|
||||
#include "code\game\objects\effects\effect_system.dm"
|
||||
#include "code\game\objects\effects\effect_system_ch.dm"
|
||||
@@ -2707,7 +2709,9 @@
|
||||
#include "code\modules\fishing\fishing_rod.dm"
|
||||
#include "code\modules\fishing\fishing_rod_vr.dm"
|
||||
#include "code\modules\fishing\fishing_vr.dm"
|
||||
#include "code\modules\flufftext\fake_attacker.dm"
|
||||
#include "code\modules\flufftext\Hallucination.dm"
|
||||
#include "code\modules\flufftext\hallucination_events.dm"
|
||||
#include "code\modules\flufftext\look_up.dm"
|
||||
#include "code\modules\flufftext\TextFilters.dm"
|
||||
#include "code\modules\food\food.dm"
|
||||
|
||||
Reference in New Issue
Block a user