Skip to content

Fixes some stuff with afterimages #6112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions code/__HELPERS/icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,8 @@ GLOBAL_LIST_EMPTY(icon_dimensions)
GLOB.icon_dimensions[icon_path] = list("width" = my_icon.Width(), "height" = my_icon.Height())
return GLOB.icon_dimensions[icon_path]

/// Strips all underlays on a different plane from an appearance.
/// Returns the stripped appearance.
/proc/strip_appearance_underlays(mutable_appearance/appearance)
var/base_plane = PLANE_TO_TRUE(appearance.plane)
for(var/mutable_appearance/underlay as anything in appearance.underlays)
Expand All @@ -1542,3 +1544,36 @@ GLOBAL_LIST_EMPTY(icon_dimensions)
if(PLANE_TO_TRUE(underlay.plane) != base_plane)
appearance.underlays -= underlay
return appearance

/**
* Copies the passed /appearance, returns a /mutable_appearance
*
* Filters out certain overlays from the copy, depending on their planes
* Prevents stuff like lighting from being copied to the new appearance
*/
/proc/copy_appearance_filter_overlays(appearance_to_copy)
var/mutable_appearance/copy = new(appearance_to_copy)
var/static/list/plane_whitelist = list(FLOAT_PLANE, GAME_PLANE, FLOOR_PLANE)

/// Ideally we'd have knowledge what we're removing but i'd have to be done on target appearance retrieval
var/list/overlays_to_keep = list()
for(var/mutable_appearance/special_overlay as anything in copy.overlays)
if(isnull(special_overlay))
continue
var/mutable_appearance/real = new()
real.appearance = special_overlay
if(PLANE_TO_TRUE(real.plane) in plane_whitelist)
overlays_to_keep += real
copy.overlays = overlays_to_keep

var/list/underlays_to_keep = list()
for(var/mutable_appearance/special_underlay as anything in copy.underlays)
if(isnull(special_underlay))
continue
var/mutable_appearance/real = new()
real.appearance = special_underlay
if(PLANE_TO_TRUE(real.plane) in plane_whitelist)
underlays_to_keep += real
copy.underlays = underlays_to_keep

return copy
11 changes: 7 additions & 4 deletions monkestation/code/modules/datums/components/glitching_state.dm
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/datum/component/glitching_state
var/count = 5
var/list/obj/effect/after_image/after_images
var/list/obj/effect/after_image/after_images = list()

/datum/component/glitching_state/Initialize(count = 5)
. = ..()
var/atom/movable/movable = parent
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
src.after_images = list()
src.count = count
if(count > 1)
for(var/number = 1 to count)
Expand Down Expand Up @@ -35,17 +34,21 @@
/datum/component/glitching_state/RegisterWithParent()
. = ..()
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_dir_change))
RegisterSignal(parent, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(do_sync))

/datum/component/glitching_state/UnregisterFromParent()
. = ..()
UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE)
UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_LIVING_SET_BODY_POSITION))

/datum/component/glitching_state/process(seconds_per_tick)
for(var/obj/effect/after_image/image as anything in after_images)
image.sync_with_parent(parent, actual_loc = FALSE)

/datum/component/glitching_state/proc/on_dir_change(datum/source, old_dir, new_dir)
/datum/component/glitching_state/proc/on_dir_change(atom/movable/source, old_dir, new_dir)
SIGNAL_HANDLER
for(var/obj/effect/after_image/image as anything in after_images)
image.sync_with_parent(parent, actual_loc = FALSE, dir_override = new_dir)

/datum/component/glitching_state/proc/do_sync(atom/movable/source)
SIGNAL_HANDLER
process()
27 changes: 18 additions & 9 deletions monkestation/code/modules/ranching/components/afterimage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -86,36 +86,45 @@
qdel(targeted_image)

/obj/effect/after_image
mouse_opacity = FALSE
anchored = 2
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
flags_1 = parent_type::flags_1 | DEMO_IGNORE_1
var/finalized_alpha = 100
var/active = FALSE
var/last_appearance_ref

/obj/effect/after_image/New(_loc, min_x = -3, max_x = 3, min_y = -3, max_y = 3, time_a = 0.5 SECONDS, time_b = 3 SECONDS, finalized_alpha = 100)
. = ..()
src.finalized_alpha = finalized_alpha
animate(src, pixel_x = 0, time = 1, loop = -1)
var/count = rand(5, 10)
for(var/number = 1 to count)
var/time = time_a + rand() * time_b
var/pixel_x = number == count ? 0 : rand(min_x, max_y)
var/pixel_y = number == count ? 0 : rand(min_y, max_y)
animate(time = time, easing = pick(LINEAR_EASING, SINE_EASING, CIRCULAR_EASING, CUBIC_EASING), pixel_x = pixel_x, pixel_y = pixel_y, loop = -1)

/obj/effect/after_image/Destroy()
last_appearance_ref = null
active = FALSE
return ..()

/obj/effect/after_image/proc/sync_with_parent(atom/movable/parent, loc_override = null, actual_loc = TRUE, dir_override = null)
if(!active)
return
set_glide_size(parent.glide_size)
if(appearance != parent.appearance)
appearance = parent.appearance
var/parent_appearance_ref = ref(parent.appearance)
if(last_appearance_ref != parent_appearance_ref)
last_appearance_ref = parent_appearance_ref
appearance = copy_appearance_filter_overlays(parent.appearance)
name = ""
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
transform = matrix()
alpha = (alpha / 255.0) * finalized_alpha
SET_PLANE_EXPLICIT(src, initial(parent.plane), parent)
var/atom/target_loc = loc_override ? loc_override : parent.loc
if(target_loc != src.loc && actual_loc)
if(target_loc != loc && actual_loc)
loc = target_loc
var/target_dir = isnull(dir_override) ? parent.dir : dir_override
if(dir != target_dir)//this is kinda important since otherwise it gets marked as demo dirty which is annoying
setDir(target_dir)

/obj/effect/after_image/Destroy()
active = FALSE
return ..()
Loading