diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 24899a65b9b..5df20aed2e4 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -844,6 +844,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define ITEM_SCALING_TRAIT "item_scaling" /// Trait given by Objects that provide blindsight #define ITEM_BLIND_TRAIT "blind_item_trait" +/// Trait given by hallucinations +#define HALLUCINATION_TRAIT "hallucination_trait" /** * Trait granted by [/mob/living/carbon/Initialize] and diff --git a/code/modules/hallucination/body.dm b/code/modules/hallucination/body.dm index 9bb8a02a0e6..25b0d1fe0c2 100644 --- a/code/modules/hallucination/body.dm +++ b/code/modules/hallucination/body.dm @@ -7,6 +7,10 @@ var/body_image_state /// The actual image we made and showed show. var/image/shown_body + /// 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 + var/spawn_under_hallucinator = FALSE /datum/hallucination/body/start() // This hallucination is purely visual, so we don't need to bother for clientless mobs @@ -14,8 +18,11 @@ return FALSE var/list/possible_points = list() - for(var/turf/open/floor/open_floor in view(hallucinator)) - possible_points += open_floor + if(spawn_under_hallucinator) + possible_points += get_turf(hallucinator) + else + for(var/turf/open/floor/open_floor in view(hallucinator)) + possible_points += open_floor if(!length(possible_points)) return FALSE @@ -23,6 +30,9 @@ shown_body = make_body_image(pick(possible_points)) hallucinator.client?.images |= shown_body + return queue_cleanup() + +/datum/hallucination/body/proc/queue_cleanup() QDEL_IN(src, rand(3 SECONDS, 5 SECONDS)) //Only seen for a brief moment. return TRUE @@ -33,7 +43,7 @@ /// 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, TURF_LAYER) + return image(body_image_file, location, body_image_state, body_layer) /datum/hallucination/body/husk random_hallucination_weight = 4 @@ -54,3 +64,38 @@ random_hallucination_weight = 1 body_image_file = 'icons/mob/nonhuman-player/alien.dmi' body_image_state = "alienother" + +/datum/hallucination/body/freezer + random_hallucination_weight = 1 + 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) + var/image/body = ..() + body.pixel_x = pick(rand(-208,-48), rand(48, 208)) + body.pixel_y = pick(rand(-208,-48), rand(48, 208)) + body.alpha = 245 + SET_PLANE_EXPLICIT(body, ABOVE_HUD_PLANE, location) + return body + +/datum/hallucination/body/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() + 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() + if(QDELETED(src)) + return + // Spook 'em before we delete + shown_body.pixel_x = (shown_body.pixel_x / 2) + shown_body.pixel_y = (shown_body.pixel_y / 2) diff --git a/code/modules/hallucination/fake_sound.dm b/code/modules/hallucination/fake_sound.dm index 75788cfb81a..609c88f8d0a 100644 --- a/code/modules/hallucination/fake_sound.dm +++ b/code/modules/hallucination/fake_sound.dm @@ -274,3 +274,15 @@ 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg', ) + +/datum/hallucination/fake_sound/weird/radio_static + volume = 75 + no_source = TRUE + sound_vary = FALSE + sound_type = 'sound/hallucinations/radio_static.ogg' + +/datum/hallucination/fake_sound/weird/ice_crack + random_hallucination_weight = 2 + volume = 100 + no_source = TRUE + sound_type = 'sound/effects/ice_shovel.ogg' diff --git a/code/modules/hallucination/ice_cube.dm b/code/modules/hallucination/ice_cube.dm new file mode 100644 index 00000000000..71f8d7d6ffb --- /dev/null +++ b/code/modules/hallucination/ice_cube.dm @@ -0,0 +1,44 @@ +/// Causes the hallucinator to believe themselves frozen in ice. Man am I glad he's frozen in there etc etc +/datum/hallucination/ice + random_hallucination_weight = 3 + + /// What icon file to use for our hallucinator + var/ice_icon = 'icons/effects/freeze.dmi' + /// What icon state to use for our hallucinator + var/ice_icon_state = "ice_cube" + /// Our ice overlay we generate + var/image/ice_overlay + /// How long will we be frozen today + var/ice_duration + /// Will we play the ice freeze sound? + var/play_ice_sound + +/datum/hallucination/ice/New(mob/living/hallucinator, duration = 6 SECONDS, play_freeze_sound = TRUE) + src.ice_duration = duration + src.play_ice_sound = play_freeze_sound + return ..() + +/datum/hallucination/ice/start() + ice_overlay = image(ice_icon, hallucinator, ice_icon_state, ABOVE_MOB_LAYER) + hallucinator.client?.images |= ice_overlay + ADD_TRAIT(hallucinator, TRAIT_IMMOBILIZED, HALLUCINATION_TRAIT) + to_chat(hallucinator, span_userdanger("You become frozen in a cube!")) + hallucinator.cause_hallucination(/datum/hallucination/fake_alert/cold, "ice hallucination", duration = (ice_duration + 6 SECONDS)) + if(play_ice_sound) + hallucinator.cause_hallucination(/datum/hallucination/fake_sound/weird/ice_crack, "ice hallucination") + + hallucinator.set_jitter_if_lower(ice_duration + 6 SECONDS) + hallucinator.set_stutter_if_lower(ice_duration + 6 SECONDS) + + QDEL_IN(src, ice_duration) + return TRUE + +/datum/hallucination/ice/Destroy() + unfreeze() + return ..() + +/datum/hallucination/ice/proc/unfreeze() + REMOVE_TRAIT(hallucinator, TRAIT_IMMOBILIZED, HALLUCINATION_TRAIT) + if(ice_overlay) + hallucinator.client?.images -= ice_overlay + ice_overlay = null diff --git a/code/modules/unit_tests/hallucination_icons.dm b/code/modules/unit_tests/hallucination_icons.dm index 337af74edae..46ee134e7ea 100644 --- a/code/modules/unit_tests/hallucination_icons.dm +++ b/code/modules/unit_tests/hallucination_icons.dm @@ -60,6 +60,12 @@ Fail("Hallucination image holder [image_holder] had an invalid / missing icon state for the icon [icon].") + // Test ice hallucination for if the ice cube icon state exists + var/datum/hallucination/ice/ice_hallucination = /datum/hallucination/ice + var/ice_hallucination_icon = initial(ice_hallucination.ice_icon) + var/ice_hallucination_icon_state = initial(ice_hallucination.ice_icon_state) + check_hallucination_icon(ice_hallucination, ice_hallucination_icon, ice_hallucination_icon_state) + /datum/unit_test/hallucination_icons/proc/check_hallucination_icon(hallucination, icon, icon_state) if(!icon) Fail("Hallucination [hallucination] forgot to set its icon file.") diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index c3a624f4a5a..4e54426858c 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/sound/effects/ice_shovel.ogg b/sound/effects/ice_shovel.ogg new file mode 100644 index 00000000000..71422d2f756 Binary files /dev/null and b/sound/effects/ice_shovel.ogg differ diff --git a/sound/hallucinations/radio_static.ogg b/sound/hallucinations/radio_static.ogg new file mode 100644 index 00000000000..32794a91eb5 Binary files /dev/null and b/sound/hallucinations/radio_static.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 7cad5724766..59a1ed88f04 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3088,6 +3088,7 @@ #include "code\modules\hallucination\fake_sound.dm" #include "code\modules\hallucination\hazard.dm" #include "code\modules\hallucination\hud_screw.dm" +#include "code\modules\hallucination\ice_cube.dm" #include "code\modules\hallucination\inhand_fake_item.dm" #include "code\modules\hallucination\nearby_fake_item.dm" #include "code\modules\hallucination\on_fire.dm"