mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-02-06 06:19:24 +00:00
## About The Pull Request Signals were initially only usable with component listeners, which while no longer the case has lead to outdated documentation, names, and a similar location in code. This pr pulls the two apart. Partially because mso thinks we should, but also because they really aren't directly linked anymore, and having them in this midstate just confuses people. [Renames comp_lookup to listen_lookup, since that's what it does](102b79694f) [Moves signal procs over to their own file](33d07d01fd) [Renames the PREQDELETING and QDELETING comsigs to drop the parent bit since they can hook to more then just comps now](335ea4ad08) [Does something similar to the attackby comsigs (PARENT -> ATOM)](210e57051d) [And finally passes over the examine signals](65917658fb) ## Why It's Good For The Game Code makes more sense, things are better teased apart, s just good imo ## Changelog 🆑 refactor: Pulled apart the last vestiges of names/docs directly linking signals to components /🆑
234 lines
7.3 KiB
Plaintext
234 lines
7.3 KiB
Plaintext
/**
|
|
* # Hallucination datum.
|
|
*
|
|
* Handles effects of a hallucination on a living mob.
|
|
* Created and triggered via the [cause hallucination proc][/mob/living/proc/cause_hallucination].
|
|
*
|
|
* See also: [the hallucination status effect][/datum/status_effect/hallucination].
|
|
*/
|
|
/datum/hallucination
|
|
/// What is this hallucination's weight in the random hallucination pool?
|
|
var/random_hallucination_weight = 0
|
|
/// Who's our next highest abstract parent type?
|
|
var/abstract_hallucination_parent = /datum/hallucination
|
|
/// Extra info about the hallucination displayed in the log.
|
|
var/feedback_details = ""
|
|
/// The mob we're targeting with the hallucination.
|
|
var/mob/living/hallucinator
|
|
|
|
/datum/hallucination/New(mob/living/hallucinator)
|
|
if(!isliving(hallucinator))
|
|
stack_trace("[type] was created without a hallucinating mob.")
|
|
qdel(src)
|
|
return
|
|
|
|
src.hallucinator = hallucinator
|
|
RegisterSignal(hallucinator, COMSIG_QDELETING, PROC_REF(target_deleting))
|
|
GLOB.all_ongoing_hallucinations += src
|
|
|
|
/// Signal proc for [COMSIG_QDELETING], if the mob hallucinating us is deletes, we should delete too.
|
|
/datum/hallucination/proc/target_deleting()
|
|
SIGNAL_HANDLER
|
|
|
|
qdel(src)
|
|
|
|
/// Starts the hallucination.
|
|
/datum/hallucination/proc/start()
|
|
SHOULD_CALL_PARENT(FALSE)
|
|
stack_trace("[type] didn't implement any hallucination effects in start.")
|
|
|
|
/datum/hallucination/Destroy()
|
|
if(hallucinator)
|
|
UnregisterSignal(hallucinator, COMSIG_QDELETING)
|
|
hallucinator = null
|
|
|
|
GLOB.all_ongoing_hallucinations -= src
|
|
return ..()
|
|
|
|
/// Returns a random turf in a ring around the hallucinator mob.
|
|
/// Useful for sound hallucinations.
|
|
/datum/hallucination/proc/random_far_turf()
|
|
var/first_offset = pick(-8, -7, -6, -5, 5, 6, 7, 8)
|
|
var/second_offset = rand(-8, 8)
|
|
var/x_offset
|
|
var/y_offset
|
|
if(prob(50))
|
|
x_offset = first_offset
|
|
y_offset = second_offset
|
|
else
|
|
x_offset = second_offset
|
|
y_offset = first_offset
|
|
|
|
return locate(hallucinator.x + x_offset, hallucinator.y + y_offset, hallucinator.z)
|
|
|
|
/// Gets a random non-security member of the crew that is at least 8 tiles away.
|
|
/datum/hallucination/proc/random_non_sec_crewmember()
|
|
var/list/possible_fakes = list()
|
|
for(var/datum/mind/possible_fake as anything in get_crewmember_minds())
|
|
// Sec won't make sense. (Neither will cap but we'll just let it slide)
|
|
if(possible_fake.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY)
|
|
continue
|
|
// Look for minds on the manifest in control of humans
|
|
var/mob/living/carbon/human/fake_body = possible_fake.current
|
|
if(!istype(fake_body) || fake_body == hallucinator)
|
|
continue
|
|
// This also won't make sense in most cases
|
|
if(get_dist(fake_body, hallucinator) < 8)
|
|
continue
|
|
possible_fakes += fake_body
|
|
|
|
return length(possible_fakes) ? pick(possible_fakes) : null
|
|
|
|
/**
|
|
* Simple effect that holds an image
|
|
* to be shown to one or multiple clients only.
|
|
*
|
|
* Pass a list of mobs in initialize() that corresponds to all mobs that can see it.
|
|
*/
|
|
/obj/effect/client_image_holder
|
|
invisibility = INVISIBILITY_OBSERVER
|
|
anchored = TRUE
|
|
|
|
/// A list of mobs which can see us.
|
|
var/list/mob/who_sees_us
|
|
/// The created image, what we look like.
|
|
var/image/shown_image
|
|
/// The icon file the image uses. If null, we have no image
|
|
var/image_icon
|
|
/// The icon state the image uses
|
|
var/image_state
|
|
/// The x pixel offset of the image
|
|
var/image_pixel_x = 0
|
|
/// The y pixel offset of the image
|
|
var/image_pixel_y = 0
|
|
/// Optional, the color of the image
|
|
var/image_color
|
|
/// The layer of the image
|
|
var/image_layer = MOB_LAYER
|
|
/// The plane of the image
|
|
var/image_plane = GAME_PLANE
|
|
|
|
/obj/effect/client_image_holder/Initialize(mapload, list/mobs_which_see_us)
|
|
. = ..()
|
|
if(isnull(mobs_which_see_us))
|
|
stack_trace("Client image holder was created with no mobs to see it.")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
shown_image = generate_image()
|
|
|
|
if(!islist(mobs_which_see_us))
|
|
mobs_which_see_us = list(mobs_which_see_us)
|
|
|
|
who_sees_us = list()
|
|
for(var/mob/seer as anything in mobs_which_see_us)
|
|
RegisterSignal(seer, COMSIG_MOB_LOGIN, PROC_REF(show_image_to))
|
|
RegisterSignal(seer, COMSIG_QDELETING, PROC_REF(remove_seer))
|
|
who_sees_us += seer
|
|
show_image_to(seer)
|
|
|
|
/obj/effect/client_image_holder/Destroy(force)
|
|
if(shown_image)
|
|
for(var/mob/seer as anything in who_sees_us)
|
|
remove_seer(seer)
|
|
shown_image = null
|
|
|
|
who_sees_us.Cut() // probably not needed but who knows
|
|
return ..()
|
|
|
|
/obj/effect/client_image_holder/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
|
|
. = ..()
|
|
if(QDELETED(src) || same_z_layer)
|
|
return
|
|
SET_PLANE(shown_image, PLANE_TO_TRUE(shown_image.plane), new_turf)
|
|
|
|
/// Signal proc to clean up references if people who see us are deleted.
|
|
/obj/effect/client_image_holder/proc/remove_seer(mob/source)
|
|
SIGNAL_HANDLER
|
|
|
|
UnregisterSignal(source, list(COMSIG_MOB_LOGIN, COMSIG_QDELETING))
|
|
hide_image_from(source)
|
|
who_sees_us -= source
|
|
|
|
// No reason to exist, anymore
|
|
if(!QDELETED(src) && !length(who_sees_us))
|
|
qdel(src)
|
|
|
|
/// Generates the image which we take on.
|
|
/obj/effect/client_image_holder/proc/generate_image()
|
|
var/image/created = image(image_icon, src, image_state, image_layer, dir = src.dir)
|
|
SET_PLANE_EXPLICIT(created, image_plane, src)
|
|
created.pixel_x = image_pixel_x
|
|
created.pixel_y = image_pixel_y
|
|
if(image_color)
|
|
created.color = image_color
|
|
return created
|
|
|
|
/// Shows the image we generated to the passed mob
|
|
/obj/effect/client_image_holder/proc/show_image_to(mob/show_to)
|
|
SIGNAL_HANDLER
|
|
|
|
show_to.client?.images |= shown_image
|
|
|
|
/// Hides the image we generated from the passed mob
|
|
/obj/effect/client_image_holder/proc/hide_image_from(mob/hide_from)
|
|
SIGNAL_HANDLER
|
|
|
|
hide_from.client?.images -= shown_image
|
|
|
|
/// Simple helper for refreshing / showing the image to everyone in our list.
|
|
/obj/effect/client_image_holder/proc/regenerate_image()
|
|
for(var/mob/seer as anything in who_sees_us)
|
|
hide_image_from(seer)
|
|
|
|
shown_image = generate_image()
|
|
|
|
for(var/mob/seer as anything in who_sees_us)
|
|
show_image_to(seer)
|
|
|
|
// Whenever we perform icon updates, regenerate our image
|
|
/obj/effect/client_image_holder/update_icon(updates = ALL)
|
|
. = ..()
|
|
regenerate_image()
|
|
|
|
// If we move for some reason, regenerate our image
|
|
/obj/effect/client_image_holder/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
|
|
. = ..()
|
|
if(!loc)
|
|
return
|
|
regenerate_image()
|
|
|
|
/obj/effect/client_image_holder/singularity_pull()
|
|
return
|
|
|
|
/obj/effect/client_image_holder/singularity_act()
|
|
return
|
|
|
|
/**
|
|
* A client-side image effect tied to the existence of a hallucination.
|
|
*/
|
|
/obj/effect/client_image_holder/hallucination
|
|
invisibility = INVISIBILITY_OBSERVER
|
|
anchored = TRUE
|
|
/// The hallucination that created us.
|
|
var/datum/hallucination/parent
|
|
|
|
/obj/effect/client_image_holder/hallucination/Initialize(mapload, list/mobs_which_see_us, datum/hallucination/parent)
|
|
. = ..()
|
|
if(!parent)
|
|
stack_trace("[type] was created without a parent hallucination.")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(parent_deleting))
|
|
src.parent = parent
|
|
|
|
/obj/effect/client_image_holder/hallucination/Destroy(force)
|
|
UnregisterSignal(parent, COMSIG_QDELETING)
|
|
parent = null
|
|
return ..()
|
|
|
|
/// Signal proc for [COMSIG_QDELETING], if our associated hallucination deletes, we should too
|
|
/obj/effect/client_image_holder/hallucination/proc/parent_deleting(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
qdel(src)
|