Adds a few (very) basic hallucinations, to keep people on their toes (#70251)

Spoiler alert!

    Adds a few extra "weird" fake body hallucinations.
        These just pop up a weird sprite somewhere in the view of the player.
        Another fun thing: Body hallucinations will appear to be floating if they spawn in nograv areas.
    Adds a "watcher" hallucination, a strange static figure that sticks on your screen until either a few minutes elapse. If you step out of view of it, then return, it will disappear.
    Adds a variant of the "fake death" hallucination which appears as if you were dusted.
    Adds two delusion - One that makes everyone appear to be ghosts, and one that makes everyone appear to be syndicates.
This commit is contained in:
MrMelbert
2022-10-07 20:18:21 -07:00
committed by GitHub
parent b761e367c9
commit bc9ba63717
6 changed files with 258 additions and 52 deletions
+107 -15
View File
@@ -1,4 +1,4 @@
/// Makes a random body appear and disappear quickly.
/// Makes a random body appear and disappear quickly in view of the hallucinator.
/datum/hallucination/body
abstract_hallucination_parent = /datum/hallucination/body
/// The file to make the body image from.
@@ -7,6 +7,8 @@
var/body_image_state
/// The actual image we made and showed show.
var/image/shown_body
/// Whether we apply the floating anim to the body
var/body_floats = FALSE
/// The layer this body will be drawn on, in case we want to bypass lighting
var/body_layer = TURF_LAYER
/// if TRUE, spawns the body under the hallucinator instead of somewhere in view
@@ -21,13 +23,19 @@
if(spawn_under_hallucinator)
possible_points += get_turf(hallucinator)
else
for(var/turf/open/floor/open_floor in view(hallucinator))
possible_points += open_floor
for(var/turf/open/open_turf in view(hallucinator))
if(open_turf.is_blocked_turf())
continue
possible_points += open_turf
if(!length(possible_points))
return FALSE
shown_body = make_body_image(pick(possible_points))
var/turf/picked = pick(possible_points)
if(isspaceturf(picked) || !picked.has_gravity())
body_floats = TRUE
shown_body = make_body_image(picked)
hallucinator.client?.images |= shown_body
return queue_cleanup()
@@ -43,15 +51,18 @@
/// Makes the image of the body to show at the location passed.
/datum/hallucination/body/proc/make_body_image(turf/location)
return image(body_image_file, location, body_image_state, body_layer)
var/image/created_image = image(body_image_file, location, body_image_state, body_layer)
if(body_floats)
DO_FLOATING_ANIM(created_image)
return created_image
/datum/hallucination/body/husk
random_hallucination_weight = 4
random_hallucination_weight = 8
body_image_file = 'icons/mob/species/human/human.dmi'
body_image_state = "husk"
/datum/hallucination/body/husk/sideways
random_hallucination_weight = 2
random_hallucination_weight = 4
/datum/hallucination/body/husk/sideways/make_body_image(turf/location)
var/image/body = ..()
@@ -60,19 +71,101 @@
body.transform = turn_matrix
return body
/datum/hallucination/body/alien
/datum/hallucination/body/ghost
random_hallucination_weight = 2
body_image_file = 'icons/mob/simple/mob.dmi'
body_image_state = "ghost"
body_floats = TRUE
/datum/hallucination/body/hole
random_hallucination_weight = 1
body_image_file = 'icons/effects/effects.dmi'
body_image_state = "blank"
/datum/hallucination/body/staticguy
random_hallucination_weight = 1
body_image_file = 'icons/effects/effects.dmi'
body_image_state = "static"
/// Our QDEL_IN timer id, so we can cancel it
var/del_timerid
/datum/hallucination/body/staticguy/Destroy()
if(!QDELETED(hallucinator))
UnregisterSignal(hallucinator, COMSIG_MOVABLE_MOVED)
if(del_timerid)
deltimer(del_timerid)
del_timerid = null
return ..()
/datum/hallucination/body/staticguy/queue_cleanup()
RegisterSignal(hallucinator, COMSIG_MOVABLE_MOVED, .proc/on_move)
del_timerid = QDEL_IN(src, rand(2 MINUTES, 3 MINUTES))
return TRUE
/// Signal proc for [COMSIG_MOVABLE_MOVED] - if we move out of view of the hallucination, it disappears, how spooky
/datum/hallucination/body/staticguy/proc/on_move(datum/source)
SIGNAL_HANDLER
// Entering its turf will cause it to fade out then delete
if(shown_body.loc == hallucinator.loc)
animate(shown_body, alpha = 0, time = 0.5 SECONDS)
deltimer(del_timerid)
del_timerid = QDEL_IN(src, 0.6 SECONDS)
return
// Staying in view will do nothing
if(shown_body.loc in view(hallucinator))
return
// Leaving view will delete it immediately
deltimer(del_timerid)
del_timerid = null
qdel(src)
/datum/hallucination/body/weird
random_hallucination_weight = 0.1 // These are very uncommon
abstract_hallucination_parent = /datum/hallucination/body/weird
/datum/hallucination/body/weird/alien
body_image_file = 'icons/mob/nonhuman-player/alien.dmi'
body_image_state = "alienother"
body_floats = TRUE
/datum/hallucination/body/freezer
random_hallucination_weight = 1
/datum/hallucination/body/weird/mini_bubblegum
body_image_file = 'icons/mob/simple/mob.dmi'
body_image_state = "horror"
/datum/hallucination/body/weird/chrono
body_image_file = 'icons/mob/simple/mob.dmi'
body_image_state = "chronostuck"
body_floats = TRUE
/datum/hallucination/body/weird/god
body_image_file = 'icons/mob/simple/mob.dmi'
body_image_state = "god"
body_floats = TRUE
/datum/hallucination/body/weird/sling
body_image_file = 'icons/mob/simple/mob.dmi'
body_image_state = "shadowling_ascended"
body_floats = TRUE
/datum/hallucination/body/weird/faceless
body_image_file = 'icons/mob/simple/simple_human.dmi'
body_image_state = "faceless"
/datum/hallucination/body/weird/bones
body_image_file = 'icons/mob/simple/simple_human.dmi'
body_image_state = "mrbones"
/datum/hallucination/body/weird/freezer
random_hallucination_weight = 0.3 // Slightly more common since it's cool (heh)
body_image_file = 'icons/effects/effects.dmi'
body_image_state = "the_freezer"
body_layer = ABOVE_ALL_MOB_LAYER
spawn_under_hallucinator = TRUE
/datum/hallucination/body/freezer/make_body_image(turf/location)
/datum/hallucination/body/weird/freezer/make_body_image(turf/location)
var/image/body = ..()
body.pixel_x = pick(rand(-208,-48), rand(48, 208))
body.pixel_y = pick(rand(-208,-48), rand(48, 208))
@@ -80,20 +173,19 @@
SET_PLANE_EXPLICIT(body, ABOVE_HUD_PLANE, location)
return body
/datum/hallucination/body/freezer/queue_cleanup()
/datum/hallucination/body/weird/freezer/queue_cleanup()
QDEL_IN(src, 12 SECONDS) //The freezer stays on screen while you're frozen
addtimer(CALLBACK(src, .proc/freeze_player), 1 SECONDS) // You barely have a moment to react before you're frozen
addtimer(CALLBACK(src, .proc/freeze_intimidate), 11.8 SECONDS)
hallucinator.cause_hallucination(/datum/hallucination/fake_sound/weird/radio_static, "freezer hallucination")
return TRUE
/datum/hallucination/body/freezer/proc/freeze_player()
/datum/hallucination/body/weird/freezer/proc/freeze_player()
if(QDELETED(src))
return
hallucinator.cause_hallucination(/datum/hallucination/ice, "freezer hallucination", duration = 11 SECONDS, play_freeze_sound = FALSE)
/datum/hallucination/body/freezer/proc/freeze_intimidate()
/datum/hallucination/body/weird/freezer/proc/freeze_intimidate()
if(QDELETED(src))
return
// Spook 'em before we delete
+64 -19
View File
@@ -26,24 +26,30 @@
/datum/hallucination/delusion/New(
mob/living/hallucinator,
duration = 30 SECONDS,
affects_us = TRUE,
affects_others = FALSE,
skip_nearby = TRUE,
play_wabbajack = FALSE,
duration,
affects_us,
affects_others,
skip_nearby,
play_wabbajack,
)
src.duration = duration
src.affects_us = affects_us
src.affects_others = affects_others
src.skip_nearby = skip_nearby
src.play_wabbajack = play_wabbajack
if(isnum(duration))
src.duration = duration
if(!isnull(affects_us))
src.affects_us = affects_us
if(!isnull(affects_others))
src.affects_others = affects_others
if(!isnull(skip_nearby))
src.skip_nearby = skip_nearby
if(!isnull(play_wabbajack))
src.play_wabbajack = play_wabbajack
return ..()
/datum/hallucination/delusion/Destroy()
if(!QDELETED(hallucinator))
for(var/image/to_remove as anything in delusions)
hallucinator.client?.images -= to_remove
if(!QDELETED(hallucinator) && LAZYLEN(delusions))
hallucinator.client?.images -= delusions
LAZYNULL(delusions)
return ..()
@@ -99,11 +105,11 @@
/datum/hallucination/delusion/custom/New(
mob/living/hallucinator,
duration = 30 SECONDS,
affects_us = TRUE,
affects_others = FALSE,
skip_nearby = FALSE,
play_wabbajack = FALSE,
duration,
affects_us,
affects_others,
skip_nearby,
play_wabbajack,
custom_icon_file,
custom_icon_state,
custom_name,
@@ -167,11 +173,50 @@
delusion_name = "demon"
/datum/hallucination/delusion/preset/cyborg
play_wabbajack = TRUE
delusion_icon_file = 'icons/mob/silicon/robots.dmi'
delusion_icon_state = "robot"
delusion_name = "cyborg"
play_wabbajack = TRUE
/datum/hallucination/delusion/preset/cyborg/make_delusion_image(mob/over_who)
. = ..()
hallucinator.playsound_local(get_turf(over_who), 'sound/voice/liveagain.ogg', 75, TRUE)
/datum/hallucination/delusion/preset/ghost
delusion_icon_file = 'icons/mob/simple/mob.dmi'
delusion_icon_state = "ghost"
delusion_name = "ghost"
affects_others = TRUE
/datum/hallucination/delusion/preset/ghost/make_delusion_image(mob/over_who)
var/image/funny_image = ..()
funny_image.name = over_who.name
DO_FLOATING_ANIM(funny_image)
return funny_image
/datum/hallucination/delusion/preset/syndies
random_hallucination_weight = 1
delusion_icon_file = 'icons/mob/simple/simple_human.dmi'
delusion_icon_state = "syndicate_space"
delusion_name = "Syndicate"
affects_others = TRUE
affects_us = FALSE
/datum/hallucination/delusion/preset/syndies/make_delusion_image(mob/over_who)
var/static/list/syndicate_icon_states
if(!syndicate_icon_states)
syndicate_icon_states = list()
for(var/state in icon_states(delusion_icon_file))
if(!findtext(state, "syndicate"))
continue
syndicate_icon_states += state
if(length(syndicate_icon_states) > 0)
delusion_name = over_who.name
delusion_icon_state = pick(syndicate_icon_states)
else
stack_trace("Hey! The hallucination [type] couldn't find a single icon state to use, it'll be invisible. Correct this.")
return ..()
+53
View File
@@ -1,3 +1,4 @@
// This hallucinations makes us suddenly think we died, stopping us / changing our hud / sending a fake deadchat message.
/datum/hallucination/death
random_hallucination_weight = 1
@@ -80,3 +81,55 @@
if(!QDELETED(src))
qdel(src)
// A subtype of death which plays a dusted animation.
/datum/hallucination/death/dust
/// List of all images we created to convey the effect to the hallucinator (so we can remove them after)
var/list/image/created_images
/datum/hallucination/death/dust/Destroy()
if(!QDELETED(hallucinator) && LAZYLEN(created_images))
hallucinator.client?.images -= created_images
LAZYNULL(created_images)
return ..()
/datum/hallucination/death/dust/start()
if(!ishuman(hallucinator))
return FALSE
var/mob/living/carbon/human/hallucinating_human = hallucinator
var/dust_icon_state = hallucinating_human.dna?.species?.dust_anim
if(!dust_icon_state)
return FALSE
. = ..()
if(!.)
return
created_images = list()
var/turf/below_hallucinating = get_turf(hallucinator)
// Apply a blank / empty image to make them look invisible to themselves
var/image/make_them_invisible = image(loc = hallucinator)
make_them_invisible.override = TRUE
created_images += make_them_invisible
// Grab the typepath of the dust animation visual so we can steal its icon (for consistency and futureproofing)
var/obj/effect/temp_visual/dust_animation/dust_source = /obj/effect/temp_visual/dust_animation
var/image/fake_dust_animation = image(initial(dust_source.icon), below_hallucinating, dust_icon_state, layer = ABOVE_MOB_LAYER)
created_images += fake_dust_animation
// Grab the typepath of remains so we can steal its icon and state (futureproofing)
var/obj/effect/decal/remains/human/remains_source = /obj/effect/decal/remains/human
var/image/fake_remains_image = image(initial(remains_source.icon), below_hallucinating, initial(remains_source.icon_state))
created_images += fake_remains_image
// Grab the typepath of an observer so we can steal its icon and state (futureproofing)
var/mob/dead/observer/observer_source = /mob/dead/observer
var/image/fake_ghost = image(initial(observer_source.icon), below_hallucinating, initial(observer_source.icon_state))
DO_FLOATING_ANIM(fake_ghost)
created_images += fake_ghost
hallucinator.client?.images |= created_images