mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
* Multiz Rework: Human Suffering Edition (Contains PLANE CUBE) * skyrat changes * bodyparts merge * unres door floorlight fix * Future upstream fix for blindness * upcoming upstream airlock fix * fix button emissive * Fix FOV markings? Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: tastyfish <crazychris32@gmail.com>
158 lines
5.8 KiB
Plaintext
158 lines
5.8 KiB
Plaintext
///A component that lets you turn an object invisible when you're standing on certain relative turfs to it, like behind a tree
|
|
/datum/component/seethrough
|
|
///List of lists that represent relative coordinates to the source atom
|
|
var/list/relative_turf_coords
|
|
///A list of turfs on which we make ourself transparent
|
|
var/list/watched_turfs
|
|
///Associate list, with client = trickery_image. Track which client is being tricked with which image
|
|
var/list/tricked_mobs = list()
|
|
|
|
///Which alpha do we animate towards?
|
|
var/target_alpha
|
|
///How long our fase in/out takes
|
|
var/animation_time
|
|
///After we somehow moved (because ss13 is godless and does not respect anything), how long do we need to stand still to feel safe to setup our "behind" area again
|
|
var/perimeter_reset_timer
|
|
|
|
///see_through_map is a define pointing to a specific map. It's basically defining the area which is considered behind. See see_through_maps.dm for a list of maps
|
|
/datum/component/seethrough/Initialize(see_through_map = SEE_THROUGH_MAP_DEFAULT, target_alpha = 100, animation_time = 0.5 SECONDS, perimeter_reset_timer = 2 SECONDS)
|
|
. = ..()
|
|
|
|
relative_turf_coords = GLOB.see_through_maps[see_through_map]
|
|
|
|
if(!isatom(parent) || !LAZYLEN(relative_turf_coords))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
relative_turf_coords = GLOB.see_through_maps[see_through_map]
|
|
src.relative_turf_coords = relative_turf_coords
|
|
src.target_alpha = target_alpha
|
|
src.animation_time = animation_time
|
|
src.perimeter_reset_timer = perimeter_reset_timer
|
|
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/dismantle_perimeter)
|
|
|
|
setup_perimeter(parent)
|
|
|
|
///Loop through a list with relative coordinate lists to mark those tiles and hide our parent when someone enters those tiles
|
|
/datum/component/seethrough/proc/setup_perimeter(atom/parent)
|
|
watched_turfs = list()
|
|
|
|
for(var/list/coordinates as anything in relative_turf_coords)
|
|
var/turf/target = TURF_FROM_COORDS_LIST(list(parent.x + coordinates[1], parent.y + coordinates[2], parent.z + coordinates[3]))
|
|
|
|
if(isnull(target))
|
|
continue
|
|
|
|
RegisterSignal(target, COMSIG_ATOM_ENTERED, .proc/on_entered)
|
|
RegisterSignal(target, COMSIG_ATOM_EXITED, .proc/on_exited)
|
|
|
|
watched_turfs.Add(target)
|
|
|
|
///Someone entered one of our tiles, so sent an override overlay and a cute animation to make us fade out a bit
|
|
/datum/component/seethrough/proc/on_entered(atom/source, atom/movable/entered)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!ismob(entered))
|
|
return
|
|
|
|
var/mob/mob = entered
|
|
|
|
if(!mob.client)
|
|
RegisterSignal(mob, COMSIG_MOB_LOGIN, .proc/trick_mob)
|
|
return
|
|
|
|
if(mob in tricked_mobs)
|
|
return
|
|
|
|
trick_mob(mob)
|
|
|
|
///Remove the screen object and make us appear solid to the client again
|
|
/datum/component/seethrough/proc/on_exited(atom/source, atom/movable/exited, direction)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!ismob(exited))
|
|
return
|
|
|
|
var/mob/mob = exited
|
|
|
|
if(!mob.client)
|
|
UnregisterSignal(mob, COMSIG_MOB_LOGIN)
|
|
return
|
|
|
|
var/turf/moving_to = get_turf(exited)
|
|
if(moving_to in watched_turfs)
|
|
return
|
|
|
|
//Check if we're being 'tricked'
|
|
if(mob in tricked_mobs)
|
|
var/image/trickery_image = tricked_mobs[mob]
|
|
animate(trickery_image, alpha = 255, time = animation_time)
|
|
tricked_mobs.Remove(mob)
|
|
UnregisterSignal(mob, COMSIG_MOB_LOGOUT)
|
|
|
|
//after playing the fade-in animation, remove the screen obj
|
|
addtimer(CALLBACK(src, /datum/component/seethrough/proc/clear_image, trickery_image, mob.client), animation_time)
|
|
|
|
///Apply the trickery image and animation
|
|
/datum/component/seethrough/proc/trick_mob(mob/fool)
|
|
var/datum/hud/our_hud = fool.hud_used
|
|
var/atom/movable/screen/plane_master/seethrough = our_hud.get_plane_master(SEETHROUGH_PLANE)
|
|
seethrough.unhide_plane(fool)
|
|
|
|
var/image/user_overlay = new(parent)
|
|
user_overlay.loc = parent
|
|
user_overlay.override = TRUE
|
|
//Special plane so we can click through the overlay
|
|
SET_PLANE_EXPLICIT(user_overlay, SEETHROUGH_PLANE, parent)
|
|
|
|
//These are inherited, but we already use the atom's loc so we end up at double the pixel offset
|
|
user_overlay.pixel_x = 0
|
|
user_overlay.pixel_y = 0
|
|
|
|
fool.client.images += user_overlay
|
|
|
|
animate(user_overlay, alpha = target_alpha, time = animation_time)
|
|
|
|
tricked_mobs[fool] = user_overlay
|
|
RegisterSignal(fool, COMSIG_MOB_LOGOUT, .proc/on_client_disconnect)
|
|
|
|
|
|
///Unrout ourselves after we somehow moved, and start a timer so we can re-restablish our behind area after standing still for a bit
|
|
/datum/component/seethrough/proc/dismantle_perimeter()
|
|
SIGNAL_HANDLER
|
|
|
|
for(var/turf in watched_turfs)
|
|
UnregisterSignal(turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED))
|
|
|
|
watched_turfs = null
|
|
clear_all_images()
|
|
|
|
//Timer override, so if our atom keeps moving the timer is reset until they stop for X time
|
|
addtimer(CALLBACK(src, /datum/component/seethrough/proc/setup_perimeter, parent), perimeter_reset_timer, TIMER_OVERRIDE | TIMER_UNIQUE)
|
|
|
|
///Remove a screen image from a client
|
|
/datum/component/seethrough/proc/clear_image(image/removee, client/remove_from)
|
|
remove_from?.images -= removee //player could've logged out during the animation, so check just in case
|
|
|
|
/datum/component/seethrough/proc/clear_all_images()
|
|
for(var/mob/fool in tricked_mobs)
|
|
var/image/trickery_image = tricked_mobs[fool]
|
|
fool.client?.images -= trickery_image
|
|
UnregisterSignal(fool, COMSIG_MOB_LOGOUT)
|
|
var/datum/hud/our_hud = fool.hud_used
|
|
var/atom/movable/screen/plane_master/seethrough = our_hud.get_plane_master(SEETHROUGH_PLANE)
|
|
seethrough.hide_plane(fool)
|
|
|
|
tricked_mobs.Cut()
|
|
|
|
///Image is removed when they log out because client gets deleted, so drop the mob reference
|
|
/datum/component/seethrough/proc/on_client_disconnect(mob/fool)
|
|
SIGNAL_HANDLER
|
|
|
|
tricked_mobs.Remove(fool)
|
|
UnregisterSignal(fool, COMSIG_MOB_LOGOUT)
|
|
RegisterSignal(fool, COMSIG_MOB_LOGIN, .proc/trick_mob)
|
|
var/datum/hud/our_hud = fool.hud_used
|
|
var/atom/movable/screen/plane_master/seethrough = our_hud.get_plane_master(SEETHROUGH_PLANE)
|
|
seethrough.hide_plane(fool)
|