/// A hallucination that makes us and (possibly) other people look like something else. /datum/hallucination/delusion abstract_hallucination_parent = /datum/hallucination/delusion hallucination_tier = HALLUCINATION_TIER_UNCOMMON /// The duration of the delusions var/duration = 30 SECONDS /// If TRUE, this delusion affects us var/affects_us = TRUE /// If TRUE, this hallucination affects all humans in existence var/affects_others = FALSE /// If TRUE, people in view of our hallcuinator won't be affected (requires affects_others) var/skip_nearby = FALSE /// If TRUE, we will play the wabbajack sound effect to the hallucinator var/play_wabbajack = FALSE /// The file the delusion image is made from var/delusion_icon_file /// The icon state of the delusion image var/delusion_icon_state /// Do we use an appearance/generated icon? If yes no icon file or state needed. var/dynamic_delusion = FALSE /// Appearance to use as a source for our image /// If this exists we'll ignore the icon/state from above var/mutable_appearance/delusion_appearance /// The name of the delusion image var/delusion_name /// An assoc list of affected mobs -> delusions of them we've made var/list/delusions /datum/hallucination/delusion/New( mob/living/hallucinator, duration, affects_us, affects_others, skip_nearby, 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) && LAZYLEN(delusions)) hallucinator.client?.images -= assoc_to_values(delusions) LAZYNULL(delusions) return ..() /datum/hallucination/delusion/start() if(!hallucinator.client || hallucinator.stat >= UNCONSCIOUS) return FALSE feedback_details += "Delusion: [delusion_name]" hallucinator.mob_flags |= MOB_HAS_SCREENTIPS_NAME_OVERRIDE RegisterSignal(hallucinator, COMSIG_MOB_REQUESTING_SCREENTIP_NAME_FROM_USER, PROC_REF(screentip_name_override)) RegisterSignal(hallucinator, COMSIG_LIVING_PERCEIVE_EXAMINE_NAME, PROC_REF(examine_name_override)) var/list/mob/living/carbon/human/funny_looking_mobs = list() // The delusion includes others - all humans if(affects_others) funny_looking_mobs |= GLOB.human_list.Copy() // The delusion includes us - we might be in it already, we might not if(affects_us && ishuman(hallucinator)) funny_looking_mobs |= hallucinator // The delusion should not inlude us else funny_looking_mobs -= hallucinator // The delusion shouldn not include anyone in view of us if(skip_nearby) for(var/mob/living/carbon/human/nearby_human in view(hallucinator)) if(nearby_human == hallucinator) // Already handled by affects_us continue funny_looking_mobs -= nearby_human for(var/mob/living/carbon/human/found_human as anything in funny_looking_mobs) var/image/funny_image = make_delusion_image(found_human) if(found_human != hallucinator) RegisterSignal(found_human, COMSIG_QDELETING, PROC_REF(on_mob_delete)) RegisterSignal(found_human, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_z_change)) // ensures the delusion image's lighting updates if the mob's lighting changes RegisterSignal(found_human, COMSIG_ATOM_HOLDER_OVERLAY_LIGHT_APPLIED, PROC_REF(on_mob_light_add)) RegisterSignal(found_human, COMSIG_ATOM_HOLDER_OVERLAY_LIGHT_REMOVED, PROC_REF(on_mob_light_remove)) LAZYSET(delusions, found_human, funny_image) hallucinator.client.images |= funny_image if(play_wabbajack) to_chat(hallucinator, span_hear("...wabbajack...wabbajack...")) hallucinator.playsound_local(get_turf(hallucinator), 'sound/effects/magic/staff_change.ogg', 50, TRUE) if(duration > 0) QDEL_IN(src, duration) return TRUE /datum/hallucination/delusion/proc/make_delusion_image(mob/over_who) var/image/funny_image if(delusion_appearance) funny_image = image(delusion_appearance, over_who) else funny_image = image(delusion_icon_file, over_who, delusion_icon_state) funny_image.name = delusion_name funny_image.override = TRUE SET_PLANE_EXPLICIT(funny_image, ABOVE_GAME_PLANE, over_who) // copies over lighting underlays for(var/image/underlay as anything in over_who.underlays) if(PLANE_TO_TRUE(underlay.plane) == O_LIGHTING_VISUAL_PLANE) funny_image.underlays += underlay return funny_image /datum/hallucination/delusion/proc/on_mob_delete(mob/living/carbon/human/source) SIGNAL_HANDLER hallucinator.client.images -= delusions[source] LAZYREMOVE(delusions, source) /datum/hallucination/delusion/proc/on_z_change(mob/living/carbon/human/source) SIGNAL_HANDLER var/image/funny_image = delusions[source] SET_PLANE_EXPLICIT(funny_image, ABOVE_GAME_PLANE, source) /datum/hallucination/delusion/proc/on_mob_light_add(mob/living/carbon/human/source, image/visible_mask, image/cone) SIGNAL_HANDLER var/image/funny_image = delusions[source] funny_image.underlays |= visible_mask if(cone) funny_image.underlays |= cone /datum/hallucination/delusion/proc/on_mob_light_remove(mob/living/carbon/human/source) SIGNAL_HANDLER var/image/funny_image = delusions[source] for(var/image/underlay as anything in funny_image.underlays) if(PLANE_TO_TRUE(underlay.plane) == O_LIGHTING_VISUAL_PLANE) funny_image.underlays -= underlay /datum/hallucination/delusion/proc/examine_name_override(datum/source, mob/living/examined, visible_name, list/name_override) SIGNAL_HANDLER if(!ishuman(examined) || !LAZYACCESS(delusions, examined)) return NONE name_override[1] = delusion_name return COMPONENT_EXAMINE_NAME_OVERRIDEN /datum/hallucination/delusion/proc/screentip_name_override(datum/source, list/returned_name, obj/item/held_item, atom/hovered) SIGNAL_HANDLER if(!ishuman(hovered) || !LAZYACCESS(delusions, hovered)) return NONE returned_name[1] = delusion_name return SCREENTIP_NAME_SET /// Used for making custom delusions. /datum/hallucination/delusion/custom random_hallucination_weight = 0 /datum/hallucination/delusion/custom/New( mob/living/hallucinator, duration, affects_us, affects_others, skip_nearby, play_wabbajack, custom_icon_file, custom_icon_state, custom_name, ) if(!custom_icon_file || !custom_icon_state) stack_trace("Custom delusion hallucination was created without any custom icon information passed.") src.delusion_icon_file = custom_icon_file src.delusion_icon_state = custom_icon_state src.delusion_name = custom_name return ..() /datum/hallucination/delusion/preset abstract_hallucination_parent = /datum/hallucination/delusion/preset random_hallucination_weight = 2 /datum/hallucination/delusion/preset/nothing delusion_icon_file = 'icons/effects/effects.dmi' delusion_icon_state = "nothing" delusion_name = "..." /datum/hallucination/delusion/preset/curse delusion_icon_file = 'icons/mob/simple/lavaland/lavaland_monsters.dmi' delusion_icon_state = "curseblob" delusion_name = "???" /datum/hallucination/delusion/preset/monkey delusion_icon_file = 'icons/mob/human/human.dmi' delusion_icon_state = "monkey" delusion_name = "monkey" /datum/hallucination/delusion/preset/monkey/start() delusion_name += " ([rand(1, 999)])" return ..() /datum/hallucination/delusion/preset/corgi delusion_icon_file = 'icons/mob/simple/pets.dmi' delusion_icon_state = "corgi" delusion_name = "corgi" /datum/hallucination/delusion/preset/carp delusion_icon_file = 'icons/mob/simple/carp.dmi' delusion_icon_state = "carp" delusion_name = "carp" /datum/hallucination/delusion/preset/skeleton delusion_icon_file = 'icons/mob/human/human.dmi' delusion_icon_state = "skeleton" delusion_name = "skeleton" /datum/hallucination/delusion/preset/zombie delusion_icon_file = 'icons/mob/human/human.dmi' delusion_icon_state = "zombie" delusion_name = "zombie" /datum/hallucination/delusion/preset/demon delusion_icon_file = 'icons/mob/simple/demon.dmi' delusion_icon_state = "slaughter_demon" delusion_name = "demon" /datum/hallucination/delusion/preset/cyborg 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/mobs/non-humanoids/cyborg/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 dynamic_delusion = TRUE random_hallucination_weight = 1 delusion_name = "Syndicate" affects_others = TRUE affects_us = FALSE hallucination_tier = HALLUCINATION_TIER_RARE /datum/hallucination/delusion/preset/syndies/make_delusion_image(mob/over_who) delusion_appearance = get_dynamic_human_appearance( mob_spawn_path = pick( /obj/effect/mob_spawn/corpse/human/syndicatesoldier, /obj/effect/mob_spawn/corpse/human/syndicatecommando, /obj/effect/mob_spawn/corpse/human/syndicatestormtrooper, ), r_hand = pick( /obj/item/knife/combat/survival, /obj/item/melee/energy/sword/saber, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/shotgun/bulldog, ), ) return ..() /datum/hallucination/delusion/preset/seccies dynamic_delusion = TRUE random_hallucination_weight = 0 delusion_name = "Security" affects_others = TRUE affects_us = FALSE /datum/hallucination/delusion/preset/seccies/make_delusion_image(mob/over_who) delusion_appearance = get_dynamic_human_appearance( outfit_path = /datum/outfit/job/security, bloody_slots = prob(5) ? ALL : NONE, r_hand = prob(15) ? /obj/item/melee/baton/security/loaded : null, l_hand = prob(15) ? /obj/item/melee/baton/security/loaded : null, ) return ..() /// Hallucination used by the nightmare vision goggles to turn everyone except you into mares /datum/hallucination/delusion/preset/mare delusion_icon_file = 'icons/obj/clothing/masks.dmi' delusion_icon_state = "horsehead" delusion_name = "mare" affects_us = FALSE affects_others = TRUE random_hallucination_weight = 0 /// Hallucination used by the path of moon heretic to turn everyone into a lunar mass /datum/hallucination/delusion/preset/moon delusion_icon_file = 'icons/mob/nonhuman-player/eldritch_mobs.dmi' delusion_icon_state = "moon_mass" delusion_name = "moon" duration = 15 SECONDS affects_others = TRUE random_hallucination_weight = 0 // Hallucination used by heretic paintings /datum/hallucination/delusion/preset/heretic dynamic_delusion = TRUE random_hallucination_weight = 0 delusion_name = "Heretic" affects_others = TRUE affects_us = FALSE duration = 11 SECONDS /datum/hallucination/delusion/preset/heretic/make_delusion_image(mob/over_who) // This code is dummy hot for DUMB reasons so let's not make a mob constantly yeah? var/static/mutable_appearance/heretic_appearance if(isnull(heretic_appearance)) heretic_appearance = get_dynamic_human_appearance(/datum/outfit/heretic, r_hand = NO_REPLACE) delusion_appearance = heretic_appearance return ..() /datum/hallucination/delusion/preset/heretic/gate delusion_name = "Mind Gate" duration = 60 SECONDS affects_us = TRUE