mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-27 17:41:50 +00:00
## About The Pull Request
516 requires float layered overlays to be using pixel_w and pixel_z
instead of pixel_x and pixel_y respectively, unless we want
visual/layering errors. This makes sense, as w,z are for visual effects
only. Sadly seems we were not entirely consistent in this, and many
things seem to have been using x,y incorrectly.
This hopefully fixes that, and thus also fixes layering issues. Complete
1:1 compatibility not guaranteed.
I did the lazy way suggested to me by SmArtKar to speed it up (Runtiming
inside apply_overlays), and this is still included in the PR to flash
out possible issues in a TM (Plus I will need someone to grep the
runtimes for me after the TM period to make sure nothing was missed).
After this is done I'll remove all these extra checks.
Lints will probably be failing for a bit, got to wait for [this
update](4b77cd487d)
to them to make it into release. Or just unlint the lines, though that's
probably gonna produce code debt
## Why It's Good For The Game
Fixes this massive 516 mess, hopefully.
closes #90281
## Changelog
🆑
refactor: Changed many of our use cases for pixel_x and pixel_y
correctly into pixel_w and pixel_z, fixing layering issues in the
process.
/🆑
---------
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: SmArtKar <master.of.bagets@gmail.com>
241 lines
7.6 KiB
Plaintext
241 lines
7.6 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
|
|
/// What tier of hallucination is this? Rarer ones should be higher
|
|
var/hallucination_tier = HALLUCINATION_TIER_NEVER
|
|
/// 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
|
|
/// Should this image holder persist if there are no seers for it?
|
|
var/persist_without_seers = FALSE
|
|
|
|
/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)
|
|
add_seer(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)
|
|
|
|
/obj/effect/client_image_holder/proc/add_seer(mob/new_seer)
|
|
RegisterSignal(new_seer, COMSIG_MOB_LOGIN, PROC_REF(show_image_to))
|
|
RegisterSignal(new_seer, COMSIG_QDELETING, PROC_REF(remove_seer))
|
|
who_sees_us += new_seer
|
|
show_image_to(new_seer)
|
|
|
|
/// 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) && !persist_without_seers)
|
|
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_w = image_pixel_x
|
|
created.pixel_z = 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(atom/singularity, current_size)
|
|
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)
|