From d095fcb52e2c66f5f4fe7b21c3a527cf6149176c Mon Sep 17 00:00:00 2001 From: Lohikar Date: Fri, 22 Sep 2023 15:23:53 -0500 Subject: [PATCH 1/8] Z-Mimic: Synchronize with upstream --- code/__defines/zmimic.dm | 29 +- code/controllers/subsystems/zcopy.dm | 325 +++++++++++++++----- code/game/atoms_movable.dm | 9 + code/game/turfs/turf_enter.dm | 6 +- code/modules/multiz/zmimic/mimic_movable.dm | 28 +- 5 files changed, 299 insertions(+), 98 deletions(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index 5f679f43597..c509012f8ab 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -1,7 +1,28 @@ +#define ZM_DESTRUCTION_TIMER(TARGET) addtimer(CALLBACK(TARGET, /datum/.proc/qdel_self), 10 SECONDS, TIMER_STOPPABLE) #define TURF_IS_MIMICKING(T) (isturf(T) && (T:z_flags & ZM_MIMIC_BELOW)) -#define CHECK_OO_EXISTENCE(OO) if (OO && !TURF_IS_MIMICKING(OO.loc)) { qdel(OO); } +#define CHECK_OO_EXISTENCE(OO) if (OO && !MOVABLE_IS_ON_ZTURF(OO) && !OO.destruction_timer) { OO.destruction_timer = ZM_DESTRUCTION_TIMER(OO); } #define UPDATE_OO_IF_PRESENT CHECK_OO_EXISTENCE(bound_overlay); if (bound_overlay) { update_above(); } +// I do not apologize. + +// These aren't intended to be used anywhere else, they just can't be undef'd because DM is dum. +#define ZM_INTERNAL_SCAN_LOOKAHEAD(M,VTR,F) ((get_step(M, M:dir)?:VTR & F) || (get_step(M, turn(M:dir, 180))?:VTR & F)) +#define ZM_INTERNAL_SCAN_LOOKBESIDE(M,VTR,F) ((get_step(M, turn(M:dir, 90))?:VTR & F) || (get_step(M, turn(M:dir, -90))?:VTR & F)) + +/// Is this movable visible from a turf that is mimicking below? Note: this does not necessarily mean *directly* below. +#define MOVABLE_IS_BELOW_ZTURF(M) (\ + isturf(M:loc) && (TURF_IS_MIMICKING(M:loc:above) \ + || ((M:z_flags & ZMM_LOOKAHEAD) && ZM_INTERNAL_SCAN_LOOKAHEAD(M, above?:z_flags, ZM_MIMIC_BELOW)) \ + || ((M:z_flags & ZMM_LOOKBESIDE) && ZM_INTERNAL_SCAN_LOOKBESIDE(M, above?:z_flags, ZM_MIMIC_BELOW))) \ +) +/// Is this movable located on a turf that is mimicking below? Note: this does not necessarily mean *directly* on. +#define MOVABLE_IS_ON_ZTURF(M) (\ + isturf(M:loc) && (TURF_IS_MIMICKING(M:loc:above) \ + || ((M:z_flags & ZMM_LOOKAHEAD) && ZM_INTERNAL_SCAN_LOOKAHEAD(M, z_flags, ZM_MIMIC_BELOW)) \ + || ((M:z_flags & ZMM_LOOKBESIDE) && ZM_INTERNAL_SCAN_LOOKBESIDE(M, z_flags, ZM_MIMIC_BELOW))) \ +) +#define MOVABLE_SHALL_MIMIC(AM) (!(AM.z_flags & ZMM_IGNORE) && MOVABLE_IS_BELOW_ZTURF(AM)) + // Turf MZ flags. #define ZM_MIMIC_BELOW 1 //! If this turf should mimic the turf on the Z below. #define ZM_MIMIC_OVERWRITE 2 //! If this turf is Z-mimicking, overwrite the turf's appearance instead of using a movable. This is faster, but means the turf cannot have its own appearance (say, edges or a translucent sprite). @@ -26,5 +47,7 @@ var/global/list/mimic_defines = list( ) // Movable flags. -#define ZMM_IGNORE 1 //! Do not copy this movable. -#define ZMM_MANGLE_PLANES 2 //! Check this movable's overlays/underlays for explicit plane use and mangle for compatibility with Z-Mimic. If you're using emissive overlays, you probably should be using this flag. Expensive, only use if necessary. +#define ZMM_IGNORE 1 //! Do not copy this movable. +#define ZMM_MANGLE_PLANES 2 //! Check this movable's overlays/underlays for explicit plane use and mangle for compatibility with Z-Mimic. If you're using emissive overlays, you probably should be using this flag. Expensive, only use if necessary. +#define ZMM_LOOKAHEAD 3 //! Look one turf ahead and one turf back when considering z-turfs that might be seeing this atom. Cheap, but not free. +#define ZMM_LOOKBESIDE 4 //! Look one turf beside (left/right) when considering z-turfs that might be seeing this atom. Cheap, but not free. diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index fdadc76814b..0bf66080ab7 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -9,6 +9,18 @@ #define SHADOWER_DARKENING_FACTOR 0.6 // The multiplication factor for openturf shadower darkness. Lighting will be multiplied by this. #define SHADOWER_DARKENING_COLOR "#999999" // The above, but as an RGB string for lighting-less turfs. +//#define ZM_RECORD_STATS // This doesn't work on O7/Neb right now. + +#ifdef ZM_RECORD_STATS +#define ZM_RECORD_START STAT_START_STOPWATCH +#define ZM_RECORD_STOP STAT_STOP_STOPWATCH +#define ZM_RECORD_WRITE(X...) STAT_LOG_ENTRY(##X) +#else +#define ZM_RECORD_START +#define ZM_RECORD_STOP +#define ZM_RECORD_WRITE(X...) +#endif + SUBSYSTEM_DEF(zcopy) name = "Z-Copy" wait = 1 @@ -25,8 +37,19 @@ SUBSYSTEM_DEF(zcopy) var/openspace_turfs = 0 var/multiqueue_skips_turf = 0 + var/multiqueue_skips_discovery = 0 var/multiqueue_skips_object = 0 + var/total_updates_turf = 0 + var/total_updates_discovery = 0 + var/total_updates_object = 0 + +#ifdef ZM_RECORD_STATS + var/list/turf_stats = list() + var/list/discovery_stats = list() + var/list/mimic_stats = list() +#endif + // Highest Z level in a given Z-group for absolute layering. // zstm[zlev] = group_max var/list/zlev_maximums = list() @@ -108,14 +131,38 @@ SUBSYSTEM_DEF(zcopy) /datum/controller/subsystem/zcopy/stat_entry() var/list/entries = list( - "Mx:[json_encode(zlev_maximums)]", + "", // newline + "ZSt: [build_zstack_display()]", // This is a human-readable list of the z-stacks known to ZM. + "ZMx: [zlev_maximums.Join(", ")]", // And this is the raw internal state. + // This one gets broken out from the below because it's more important. "Q: { T: [queued_turfs.len - (qt_idex - 1)] O: [queued_overlays.len - (qo_idex - 1)] }", - "T: { T: [openspace_turfs] O: [openspace_overlays] }", - "Sk: { T: [multiqueue_skips_turf] O: [multiqueue_skips_object] }", + // In order: Total, Queued, Skipped + "T(O): { T: [openspace_turfs] O: [openspace_overlays] }", + "T(U): { T: [total_updates_turf] D: [total_updates_discovery] O: [total_updates_object] }", + "Sk: { T: [multiqueue_skips_turf] D: [multiqueue_skips_discovery] O: [multiqueue_skips_object] }", "F: { H: [fixup_hit] M: [fixup_miss] N: [fixup_noop] FC: [fixup_cache.len] FKG: [fixup_known_good.len] }" ) ..(entries.Join("\n\t")) +// 1, 2, 3..=7, 8 +/datum/controller/subsystem/zcopy/proc/build_zstack_display() + if (!zlev_maximums.len) + return "" + var/list/zmx = list() + var/idx = 1 + var/span_ctr = 0 + do + if (zlev_maximums[idx] != idx) + span_ctr += 1 + else if (span_ctr) + zmx += "[idx - span_ctr]..=[idx]" + span_ctr = 0 + else + zmx += "[idx]" + idx += 1 + while (idx <= zlev_maximums.len) + return jointext(zmx, ", ") + /datum/controller/subsystem/zcopy/Initialize(timeofday) calculate_zstack_limits() // Flush the queue. @@ -169,8 +216,16 @@ SUBSYSTEM_DEF(zcopy) if (!no_mc_tick) MC_SPLIT_TICK + tick_turfs(no_mc_tick) + + if (!no_mc_tick) + MC_SPLIT_TICK + + tick_mimic(no_mc_tick) + +// - Turf mimic - +/datum/controller/subsystem/zcopy/proc/tick_turfs(no_mc_tick) var/list/curr_turfs = queued_turfs - var/list/curr_ov = queued_overlays while (qt_idex <= curr_turfs.len) var/turf/T = curr_turfs[qt_idex] @@ -188,6 +243,7 @@ SUBSYSTEM_DEF(zcopy) if (T.z_queued > 1) T.z_queued -= 1 multiqueue_skips_turf += 1 + if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) @@ -197,12 +253,23 @@ SUBSYSTEM_DEF(zcopy) // Z-Turf on the bottom-most level, just fake-copy space (or baseturf). // It's impossible for anything to be on the synthetic turf, so ignore the rest of the ZM machinery. if (!T.below) + ZM_RECORD_START flush_z_state(T) if (T.z_flags & ZM_MIMIC_BASETURF) simple_appearance_copy(T, get_base_turf_by_area(T), OPENTURF_MAX_PLANE) else simple_appearance_copy(T, SSskybox.dust_cache["[((T.x + T.y) ^ ~(T.x * T.y) + T.z) % 25]"]) + T.z_generation += 1 + T.z_queued -= 1 + total_updates_turf += 1 + + if (T.above) + T.above.update_mimic() + + ZM_RECORD_STOP + ZM_RECORD_WRITE(turf_stats, "Fake: [T.type] on [T.z]") + if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) @@ -215,9 +282,12 @@ SUBSYSTEM_DEF(zcopy) T.z_generation += 1 + ZM_RECORD_START + // Get the bottom-most turf, the one we want to mimic. + // Baseturf mimics act as false bottoms of the stack. var/turf/Td = T - while (Td.below) + while (Td.below && !(Td.z_flags & ZM_MIMIC_BASETURF)) Td = Td.below // Depth must be the depth of the *visible* turf, not self. @@ -231,6 +301,15 @@ SUBSYSTEM_DEF(zcopy) flush_z_state(T) simple_appearance_copy(T, get_base_turf_by_area(T), t_target) + if (T.above) + T.above.update_mimic() + + total_updates_turf += 1 + T.z_queued -= 1 + + ZM_RECORD_STOP + ZM_RECORD_WRITE(turf_stats, "Simple: [T.type] on [T.z]") + if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) @@ -286,11 +365,16 @@ SUBSYSTEM_DEF(zcopy) // Handle below atoms. - // Add everything below us to the update queue. + // Add everything below us to the discovery queue. for (var/thing in T.below) var/atom/movable/object = thing if (QDELETED(object) || (object.z_flags & ZMM_IGNORE) || object.loc != T.below || object.invisibility == INVISIBILITY_ABSTRACT) - // Don't queue deleted stuff, stuff that's not visible, blacklisted stuff, or stuff that's centered on another tile but intersects ours. + /* Don't queue: + - (q)deleted objects + - Explicitly ignored objects + - Objects not rooted on this turf (multitiles) + - Always-invisible atoms + */ continue // Special case: these are merged into the shadower to reduce memory usage. @@ -298,63 +382,20 @@ SUBSYSTEM_DEF(zcopy) T.shadower.copy_lighting(object) continue - if (!object.bound_overlay) // Generate a new overlay if the atom doesn't already have one. - object.bound_overlay = new(T) - object.bound_overlay.associated_atom = object - - var/override_depth - var/original_type = object.type - var/original_z = object.z - var/have_performed_fixup = FALSE - - switch (object.type) - // Layering for recursive mimic needs to be inherited. - if (/atom/movable/openspace/mimic) - var/atom/movable/openspace/mimic/OOO = object - original_type = OOO.mimiced_type - override_depth = OOO.override_depth - original_z = OOO.original_z - have_performed_fixup = OOO.have_performed_fixup - - // If this is a turf proxy (the mimic for a non-OVERWRITE turf), it needs to respect space parallax if relevant. - if (/atom/movable/openspace/turf_proxy) - if (T.z_eventually_space) - // Yes, this is an awful hack; I don't want to add yet another override_* var. - override_depth = OPENTURF_MAX_PLANE - SPACE_PLANE - - if (/atom/movable/openspace/turf_mimic) - original_z += 1 - - var/atom/movable/openspace/mimic/OO = object.bound_overlay - - // If the OO was queued for destruction but was claimed by another OT, stop the destruction timer. - if (OO.destruction_timer) - deltimer(OO.destruction_timer) - OO.destruction_timer = null - - OO.depth = override_depth || min(zlev_maximums[T.z] - original_z, OPENTURF_MAX_DEPTH) - - // These types need to be pushed a layer down for bigturfs to function correctly. - switch (original_type) - if (/atom/movable/openspace/multiplier, /atom/movable/openspace/turf_proxy) - if (OO.depth < OPENTURF_MAX_DEPTH) - OO.depth += 1 - - OO.mimiced_type = original_type - OO.override_depth = override_depth - OO.original_z = original_z - OO.have_performed_fixup ||= have_performed_fixup - - // Multi-queue to maintain ordering of updates to these - // queueing it multiple times will result in only the most recent - // actually processing. - OO.queued += 1 - queued_overlays += OO + // If an atom already has an overlay, we probably don't need to discover it again. + // ...but we need to force it if the object was salvaged from another zturf. + if (!object.bound_overlay || object.bound_overlay.destruction_timer) + discover_movable(object, T) T.z_queued -= 1 if (T.above) T.above.update_mimic() + total_updates_turf += 1 + + ZM_RECORD_STOP + ZM_RECORD_WRITE(turf_stats, "Complex: [T.type] on [T.z]") + if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) @@ -364,9 +405,9 @@ SUBSYSTEM_DEF(zcopy) curr_turfs.Cut(1, qt_idex) qt_idex = 1 - if (!no_mc_tick) - MC_SPLIT_TICK - +// - Phase: Mimic update -- actually update the mimics' appearance, order sensitive - +/datum/controller/subsystem/zcopy/proc/tick_mimic(no_mc_tick) + var/list/curr_ov = queued_overlays while (qo_idex <= curr_ov.len) var/atom/movable/openspace/mimic/OO = curr_ov[qo_idex] curr_ov[qo_idex] = null @@ -379,8 +420,9 @@ SUBSYSTEM_DEF(zcopy) break continue - if (QDELETED(OO.associated_atom)) // This shouldn't happen, but just in-case. + if (QDELETED(OO.associated_atom)) // This shouldn't happen. qdel(OO) + log_debug("Z-Mimic: Received mimic with QDELETED parent ([OO.associated_atom || ""])") if (no_mc_tick) CHECK_TICK @@ -392,21 +434,24 @@ SUBSYSTEM_DEF(zcopy) if (OO.queued > 1) OO.queued -= 1 multiqueue_skips_object += 1 + if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) break continue + ZM_RECORD_START + // Actually update the overlay. if (OO.dir != OO.associated_atom.dir) - OO.set_dir(OO.associated_atom.dir) + OO.dir = OO.associated_atom.dir // updates are propagated up another way, don't use set_dir + OO.appearance = OO.associated_atom + OO.z_flags = OO.associated_atom.z_flags if (OO.particles != OO.associated_atom.particles) OO.particles = OO.associated_atom.particles - OO.appearance = OO.associated_atom - OO.z_flags = OO.associated_atom.z_flags OO.plane = OPENTURF_MAX_PLANE - OO.depth OO.opacity = FALSE @@ -422,6 +467,11 @@ SUBSYSTEM_DEF(zcopy) if (OO.bound_overlay) // If we have a bound overlay, queue it too. OO.update_above() + total_updates_object += 1 + + ZM_RECORD_STOP + ZM_RECORD_WRITE(mimic_stats, OO.mimiced_type) + if (no_mc_tick) CHECK_TICK else if (MC_TICK_CHECK) @@ -431,14 +481,85 @@ SUBSYSTEM_DEF(zcopy) curr_ov.Cut(1, qo_idex) qo_idex = 1 +// return: is-invalid +/datum/controller/subsystem/zcopy/proc/discover_movable(atom/movable/object) + ASSERT(!QDELETED(object)) + + var/turf/Tloc = object.loc + if (!isturf(Tloc) || !Tloc.above) + return TRUE + + var/turf/T = Tloc.above + + ZM_RECORD_START + + if (!object.bound_overlay) + var/atom/movable/openspace/mimic/M = new(T) + object.bound_overlay = M + M.associated_atom = object + if (TURF_IS_MIMICKING(M.loc)) + .(M) + + var/override_depth + var/original_type = object.type + var/original_z = object.z + + switch (object.type) + // Layering for recursive mimic needs to be inherited. + if (/atom/movable/openspace/mimic) + var/atom/movable/openspace/mimic/OOO = object + original_type = OOO.mimiced_type + override_depth = OOO.override_depth + original_z = OOO.original_z + + // If this is a turf proxy (the mimic for a non-OVERWRITE turf), it needs to respect space parallax if relevant. + if (/atom/movable/openspace/turf_proxy) + if (T.z_eventually_space) + // Yes, this is an awful hack; I don't want to add yet another override_* var. + override_depth = OPENTURF_MAX_PLANE - SPACE_PLANE + + var/atom/movable/openspace/mimic/OO = object.bound_overlay + + // If the OO was queued for destruction but was claimed by another OT, stop the destruction timer. + if (OO.destruction_timer) + deltimer(OO.destruction_timer) + OO.destruction_timer = null + + OO.depth = override_depth || min(zlev_maximums[T.z] - original_z, OPENTURF_MAX_DEPTH) + + switch (original_type) + // These types need to be pushed a layer down for bigturfs to function correctly. + if (/atom/movable/openspace/turf_proxy, /atom/movable/openspace/turf_mimic) + OO.depth += 1 + if (/atom/movable/openspace/multiplier) + OO.depth += 1 + + OO.mimiced_type = original_type + OO.override_depth = override_depth + OO.original_z = original_z + + // Multi-queue to maintain ordering of updates to these + // queueing it multiple times will result in only the most recent + // actually processing. + OO.queued += 1 + queued_overlays += OO + + total_updates_discovery += 1 + + ZM_RECORD_STOP + ZM_RECORD_WRITE(discovery_stats, "Depth [OO.depth] on [OO.z]") + + return FALSE + /datum/controller/subsystem/zcopy/proc/flush_z_state(turf/T) - if (T.below.mimic_above_copy) - QDEL_NULL(T.below.mimic_above_copy) - if (T.below.mimic_proxy) - QDEL_NULL(T.below.mimic_proxy) - for (var/atom/movable/openspace/OO in T) - if (istype(OO, /atom/movable/openspace/mimic)) - qdel(OO) + if (T.below) // Z-Mimic turfs aren't necessarily above another turf. + if (T.below.mimic_above_copy) + QDEL_NULL(T.below.mimic_above_copy) + if (T.below.mimic_proxy) + QDEL_NULL(T.below.mimic_proxy) + QDEL_NULL(T.mimic_underlay) + for (var/atom/movable/openspace/mimic/OO in T) + qdel(OO) /datum/controller/subsystem/zcopy/proc/simple_appearance_copy(turf/T, new_appearance, target_plane) if (T.z_flags & ZM_MIMIC_OVERWRITE) @@ -523,7 +644,7 @@ SUBSYSTEM_DEF(zcopy) fixed_underlays[i] = fixed_appearance if (mutated) - for (var/i in 1 to fixed_overlays.len) + for (var/i in 1 to fixed_underlays.len) if (fixed_underlays[i] == null) fixed_underlays[i] = appearance:underlays[i] @@ -551,6 +672,7 @@ SUBSYSTEM_DEF(zcopy) return MA #define FMT_DEPTH(X) (X == null ? "(null)" : X) +#define FMT_OK(X) (X) ? "OK" : "MISMATCH" // This is a dummy object used so overlays can be shown in the analyzer. /atom/movable/openspace/debug @@ -583,7 +705,7 @@ SUBSYSTEM_DEF(zcopy) "", "

Analysis of [T] at [T.x],[T.y],[T.z]

", "Queue occurrences: [T.z_queued]", - "Above space: Apparent [T.z_eventually_space ? "Yes" : "No"], Actual [is_above_space ? "Yes" : "No"] - [T.z_eventually_space == is_above_space ? "OK" : "MISMATCH"]", + "Above space: Apparent [T.z_eventually_space ? "Yes" : "No"], Actual [is_above_space ? "Yes" : "No"] - [FMT_OK(T.z_eventually_space == is_above_space)]", "Z Flags: [english_list(bitfield2list(T.z_flags, global.mimic_defines), "(none)")]", "Has Shadower: [T.shadower ? "Yes" : "No"]", "Has turf proxy: [T.mimic_proxy ? "Yes" : "No"]", @@ -592,11 +714,13 @@ SUBSYSTEM_DEF(zcopy) "Below: [!T.below ? "(nothing)" : "[T.below] at [T.below.x],[T.below.y],[T.below.z]"]", "Depth: [FMT_DEPTH(T.z_depth)] [T.z_depth == OPENTURF_MAX_DEPTH ? "(max)" : ""]", "Generation: [T.z_generation]", - "Update count: Claimed [claimed_update_count], Actual [real_update_count] - [claimed_update_count == real_update_count ? "OK" : "MISMATCH"]", + "Update count: Claimed [claimed_update_count], Actual [real_update_count] - [FMT_OK(claimed_update_count == real_update_count)]", "
    " ) - if (T.z_flags & ZM_MIMIC_BASETURF) + if (!T.below) + out += "

    Using synthetic rendering (Not Z).

    " + else if (T.z_flags & ZM_MIMIC_BASETURF) out += "

    Using synthetic rendering (BASETURF).

    " var/list/found_oo = list(T) @@ -640,7 +764,7 @@ SUBSYSTEM_DEF(zcopy) for (var/d in 0 to OPENTURF_MAX_DEPTH) var/pl = OPENTURF_MAX_PLANE - d if (!atoms_list_list["[pl]"]) - out += "Depth [d], plane [pl] — empty" + out += "Depth [d], planes [pl] — empty" continue out += "Depth [d], plane [pl]" @@ -672,9 +796,13 @@ SUBSYSTEM_DEF(zcopy) /datum/controller/subsystem/zcopy/proc/debug_fmt_thing(atom/A, list/out, turf/original) if (istype(A, /atom/movable/openspace/mimic)) var/atom/movable/openspace/mimic/OO = A + var/base = "
  • [fmt_label("Mimic", A)] plane [A.plane], layer [A.layer], depth [FMT_DEPTH(OO.depth)]" + if (QDELETED(OO.associated_atom)) // This shouldn't happen, but can if the deletion hook is not working. + return "[base] - [OO.type] copying ([OO.mimiced_type]) - ORPHANED
  • " + var/atom/movable/AA = OO.associated_atom var/copied_type = AA.type == OO.mimiced_type ? "[AA.type] \[direct\]" : "[AA.type], eventually [OO.mimiced_type]" - return "
  • [fmt_label("Mimic", A)] plane [A.plane], layer [A.layer], depth [FMT_DEPTH(OO.depth)], fixup [OO.have_performed_fixup ? "Y" : "N"], associated Z-level [AA.z] - [OO.type] copying [AA] ([copied_type])
  • " + return "[base], associated Z-level [AA.z] - [OO.type] copying [AA] ([copied_type])" else if (istype(A, /atom/movable/openspace/turf_mimic)) var/atom/movable/openspace/turf_mimic/DC = A @@ -683,9 +811,11 @@ SUBSYSTEM_DEF(zcopy) else if (isturf(A)) if (A == original) return "
  • [fmt_label("Turf", A)] plane [A.plane], layer [A.layer], depth [FMT_DEPTH(A:z_depth)], Z-level [A.z] - [A] ([A.type]) - SELF
  • " + else // foreign turfs - not visible here, but sometimes good for figuring out layering -- showing these is currently not enabled return "
  • [fmt_label("Foreign Turf", A)] plane [A.plane], layer [A.layer], depth [FMT_DEPTH(A:z_depth)], Z-level [A.z] - [A] ([A.type]) - FOREIGN
  • " + else if (A.type == /atom/movable/openspace/multiplier) return "
  • [fmt_label("Shadower", A)] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type])
  • " @@ -694,7 +824,7 @@ SUBSYSTEM_DEF(zcopy) else if (A.type == /atom/movable/openspace/debug/turf) var/atom/movable/openspace/debug/turf/VTO = A - return "
  • [fmt_label("VTO", VTO.parent)] plane [VTO.plane], layer [VTO.layer], computed depth [FMT_DEPTH(VTO.computed_depth)] - [VTO.parent] ([VTO.parent.type]) - FOREIGN" + return "
  • [fmt_label("VTO", VTO.parent)] plane [VTO.plane], layer [VTO.layer], computed depth [FMT_DEPTH(VTO.computed_depth)] - [VTO.parent] ([VTO.parent.type]) - FOREIGN" else if (A.type == /atom/movable/openspace/turf_proxy) return "
  • [fmt_label("Turf Proxy", A)] plane [A.plane], layer [A.layer], Z-level [A.z] - [A] ([A.type])
  • " @@ -717,3 +847,38 @@ SUBSYSTEM_DEF(zcopy) out += "No atoms." #undef FMT_DEPTH +#undef FMT_OK +#undef ZM_RECORD_START +#undef ZM_RECORD_STOP +#undef ZM_RECORD_WRITE + +#ifdef ZM_RECORD_STATS +/client/proc/zms_display_turf() + set name = "ZM Stats - 1Turf" + set category = "Debug" + + if(!check_rights(R_DEBUG)) + return + + render_stats(SSzcopy.turf_stats, src) + +/client/proc/zms_display_discovery() + set name = "ZM Stats - 2Discovery" + set category = "Debug" + + if(!check_rights(R_DEBUG)) + return + + render_stats(SSzcopy.discovery_stats, src) + +/client/proc/zms_display_mimic() + set name = "ZM Stats - 3Mimic" + set category = "Debug" + + if(!check_rights(R_DEBUG)) + return + + render_stats(SSzcopy.mimic_stats, src) + + +#endif diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 4c3372fc83b..0588748a8d6 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -254,6 +254,15 @@ L = thing L.source_atom.update_light() + // Z-Mimic. + if (bound_overlay) + // The overlay will handle cleaning itself up on non-openspace turfs. + bound_overlay.forceMove(get_step(src, UP)) + if (bound_overlay.dir != dir) + bound_overlay.set_dir(dir) + else if (isturf(loc) && (!old_loc || !TURF_IS_MIMICKING(old_loc)) && MOVABLE_SHALL_MIMIC(src)) + SSzcopy.discover_movable(src) + //called when src is thrown into hit_atom /atom/movable/proc/throw_impact(atom/hit_atom, var/datum/thrownthing/TT) SHOULD_CALL_PARENT(TRUE) diff --git a/code/game/turfs/turf_enter.dm b/code/game/turfs/turf_enter.dm index ddb26633928..107b9aa1018 100644 --- a/code/game/turfs/turf_enter.dm +++ b/code/game/turfs/turf_enter.dm @@ -5,7 +5,7 @@ if(!istype(mover) || !(mover.movable_flags & MOVABLE_FLAG_PROXMOVE)) return for(var/atom/movable/neighbor in range(1)) - if(objects > ENTER_PROXIMITY_LOOP_SANITY) + if(objects > ENTER_PROXIMITY_LOOP_SANITY) break // Don't let ore piles kill the server as well as the client. if(neighbor.movable_flags & MOVABLE_FLAG_PROXMOVE) objects++ @@ -48,7 +48,3 @@ if((mat.gas_flags & XGM_GAS_CONTAMINANT) && env.gas[g] > mat.gas_overlay_limit + 1) I.contaminate() break - - // Handle zmimic - if(!A.bound_overlay && !(A.z_flags & ZMM_IGNORE) && TURF_IS_MIMICKING(above)) - above.update_mimic() diff --git a/code/modules/multiz/zmimic/mimic_movable.dm b/code/modules/multiz/zmimic/mimic_movable.dm index d550f6b3907..d31a30330c4 100644 --- a/code/modules/multiz/zmimic/mimic_movable.dm +++ b/code/modules/multiz/zmimic/mimic_movable.dm @@ -15,13 +15,6 @@ else // Not a turf, so we need to destroy immediately instead of waiting for the destruction timer to proc. qdel(bound_overlay) -/atom/movable/Move() - . = ..() - if (. && bound_overlay) - bound_overlay.forceMove(get_step(src, UP)) - if (bound_overlay.dir != dir) - bound_overlay.set_dir(dir) - /atom/movable/set_dir(ndir) . = ..() if (. && bound_overlay) @@ -54,7 +47,7 @@ simulated = FALSE anchored = TRUE mouse_opacity = FALSE - abstract_type = /atom/movable/openspace // unsure if this is valid, check with Lohi + abstract_type = /atom/movable/openspace // unsure if this is valid, check with Lohi -- Yes, it's valid. /atom/movable/openspace/can_fall() return FALSE @@ -84,6 +77,7 @@ var/turf/myturf = loc if (istype(myturf)) myturf.shadower = null + return ..() /atom/movable/openspace/multiplier/proc/copy_lighting(atom/movable/lighting_overlay/LO) @@ -163,18 +157,32 @@ . = associated_atom.examine(arglist(args)) // just pass all the args to the copied atom /atom/movable/openspace/mimic/forceMove(turf/dest) + var/atom/old_loc = loc . = ..() if (TURF_IS_MIMICKING(dest)) if (destruction_timer) deltimer(destruction_timer) destruction_timer = null + if (old_loc.z != loc.z) + reset_internal_layering() else if (!destruction_timer) - destruction_timer = addtimer(CALLBACK(src, /datum/.proc/qdel_self), 10 SECONDS, TIMER_STOPPABLE) + destruction_timer = ZM_DESTRUCTION_TIMER(src) // Called when the turf we're on is deleted/changed. /atom/movable/openspace/mimic/proc/owning_turf_changed() if (!destruction_timer) - destruction_timer = addtimer(CALLBACK(src, /datum/.proc/qdel_self), 10 SECONDS, TIMER_STOPPABLE) + destruction_timer = ZM_DESTRUCTION_TIMER(src) + +/atom/movable/openspace/mimic/proc/reset_internal_layering() + if (bound_overlay.override_depth) + depth = bound_overlay.override_depth + else if (isturf(associated_atom.loc)) + depth = min(SSzcopy.zlev_maximums[associated_atom.z] - associated_atom.z, OPENTURF_MAX_DEPTH) + override_depth = depth + + plane = OPENTURF_MAX_PLANE - depth + + bound_overlay?.reset_internal_layering() // -- TURF PROXY -- From 80049e5e5d49b6b823530fab90c310737a3e7432 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sun, 28 Jan 2024 02:38:26 -0600 Subject: [PATCH 2/8] zm: Add ZM_OVERRIDE --- code/__defines/zmimic.dm | 1 + code/controllers/subsystems/zcopy.dm | 10 ++++++++-- code/modules/multiz/zmimic/mimic_turf.dm | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index c509012f8ab..4483fee9a7d 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -31,6 +31,7 @@ #define ZM_MIMIC_NO_AO 16 //! If the turf shouldn't apply regular turf AO and only do Z-mimic AO. #define ZM_NO_OCCLUDE 32 //! Don't occlude below atoms if we're a non-mimic z-turf. #define ZM_MIMIC_BASETURF 64 //! Mimic baseturf instead of the below atom. Sometimes useful for elevators. +#define ZM_OVERRIDE 128 // If this turf is being copied, read the `z_appearance` var instead of our real appearance. // Convenience flag. #define ZM_MIMIC_DEFAULTS (ZM_MIMIC_BELOW|ZM_ALLOW_LIGHTING) diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index 0bf66080ab7..c66026adf6c 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -325,11 +325,17 @@ SUBSYSTEM_DEF(zcopy) T.z_eventually_space = TRUE t_target = SPACE_PLANE + var/appearance_target + if (T.below.z_flags & ZM_OVERRIDE) + appearance_target = T.below.z_appearance + else + appearance_target = Td + if (T.z_flags & ZM_MIMIC_OVERWRITE) // This openturf doesn't care about its icon, so we can just overwrite it. if (T.below.mimic_proxy) QDEL_NULL(T.below.mimic_proxy) - T.appearance = T.below + T.appearance = appearance_target // This used to be T.below rather than Td, not sure why. Legacy artifact? T.name = initial(T.name) T.desc = initial(T.desc) T.gender = initial(T.gender) @@ -340,7 +346,7 @@ SUBSYSTEM_DEF(zcopy) if (!T.below.mimic_proxy) T.below.mimic_proxy = new(T) var/atom/movable/openspace/turf_proxy/TO = T.below.mimic_proxy - TO.appearance = Td + TO.appearance = appearance_target TO.name = T.name TO.gender = T.gender // Need to grab this too so PLURAL works properly in examine. TO.opacity = FALSE diff --git a/code/modules/multiz/zmimic/mimic_turf.dm b/code/modules/multiz/zmimic/mimic_turf.dm index 07d58a0e959..3bc71a7e6dd 100644 --- a/code/modules/multiz/zmimic/mimic_turf.dm +++ b/code/modules/multiz/zmimic/mimic_turf.dm @@ -15,6 +15,8 @@ /// If this Z-turf leads to space, uninterrupted. var/tmp/z_eventually_space = FALSE var/z_flags = 0 + /// If ZM_OVERRIDE is set, use this var for appearance instead of the `appearance` BYOND-var. Anything that's valid in `appearance` is valid here. + var/z_appearance // debug var/tmp/z_depth From 51b82694c0a2b2a6176080b1839add3ff5f2ae7c Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sun, 28 Jan 2024 02:47:40 -0600 Subject: [PATCH 3/8] 515 bad --- code/__defines/zmimic.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index 4483fee9a7d..a3283690f7f 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -1,4 +1,4 @@ -#define ZM_DESTRUCTION_TIMER(TARGET) addtimer(CALLBACK(TARGET, /datum/.proc/qdel_self), 10 SECONDS, TIMER_STOPPABLE) +#define ZM_DESTRUCTION_TIMER(TARGET) addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, qdel_self)), 10 SECONDS, TIMER_STOPPABLE) #define TURF_IS_MIMICKING(T) (isturf(T) && (T:z_flags & ZM_MIMIC_BELOW)) #define CHECK_OO_EXISTENCE(OO) if (OO && !MOVABLE_IS_ON_ZTURF(OO) && !OO.destruction_timer) { OO.destruction_timer = ZM_DESTRUCTION_TIMER(OO); } #define UPDATE_OO_IF_PRESENT CHECK_OO_EXISTENCE(bound_overlay); if (bound_overlay) { update_above(); } From 90149cd9ea4e56f2c9093a15a888e3fc5709a9a2 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sun, 28 Jan 2024 02:59:04 -0600 Subject: [PATCH 4/8] zm: Add ZMM_WIDE_LOAD --- code/__defines/zmimic.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index a3283690f7f..0b35df4d933 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -33,8 +33,9 @@ #define ZM_MIMIC_BASETURF 64 //! Mimic baseturf instead of the below atom. Sometimes useful for elevators. #define ZM_OVERRIDE 128 // If this turf is being copied, read the `z_appearance` var instead of our real appearance. -// Convenience flag. -#define ZM_MIMIC_DEFAULTS (ZM_MIMIC_BELOW|ZM_ALLOW_LIGHTING) +// Convenience flags. +#define ZM_MIMIC_DEFAULTS (ZM_MIMIC_BELOW|ZM_ALLOW_LIGHTING) //! Common defaults for zturfs. +#define ZMM_WIDE_LOAD (ZMM_LOOKAHEAD | ZMM_LOOKBESIDE) //! Atom is big and needs to scan one extra turf in both X and Y. This only extends the range by one turf. Cheap, but not free. // For debug purposes, should contain the above defines in ascending order. var/global/list/mimic_defines = list( From faa65fb3619f2bf3667f02fc3091a5b520a088d1 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sun, 28 Jan 2024 03:07:46 -0600 Subject: [PATCH 5/8] zm: Add ZM_NO_SHADOW --- code/__defines/zmimic.dm | 3 +- code/controllers/subsystems/zcopy.dm | 10 ++++- code/modules/multiz/zmimic/mimic_movable.dm | 41 +++++++++++---------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index 0b35df4d933..2ee55949e4d 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -31,7 +31,8 @@ #define ZM_MIMIC_NO_AO 16 //! If the turf shouldn't apply regular turf AO and only do Z-mimic AO. #define ZM_NO_OCCLUDE 32 //! Don't occlude below atoms if we're a non-mimic z-turf. #define ZM_MIMIC_BASETURF 64 //! Mimic baseturf instead of the below atom. Sometimes useful for elevators. -#define ZM_OVERRIDE 128 // If this turf is being copied, read the `z_appearance` var instead of our real appearance. +#define ZM_OVERRIDE 128 //! If this turf is being copied, read the `z_appearance` var instead of our real appearance. +#define ZM_NO_SHADOW 256 //! If this turf is being copied, hide the shadower. // Convenience flags. #define ZM_MIMIC_DEFAULTS (ZM_MIMIC_BELOW|ZM_ALLOW_LIGHTING) //! Common defaults for zturfs. diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index 5c209dd2c52..f251c6d6e5a 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -371,6 +371,8 @@ SUBSYSTEM_DEF(zcopy) // Handle below atoms. + var/shadower_set = FALSE + // Add everything below us to the discovery queue. for (var/thing in T.below) var/atom/movable/object = thing @@ -385,7 +387,7 @@ SUBSYSTEM_DEF(zcopy) // Special case: these are merged into the shadower to reduce memory usage. if (object.type == /atom/movable/lighting_overlay) - T.shadower.copy_lighting(object) + T.shadower.copy_lighting(object, !(T.below.z_flags & ZM_NO_SHADOW)) continue // If an atom already has an overlay, we probably don't need to discover it again. @@ -393,6 +395,12 @@ SUBSYSTEM_DEF(zcopy) if (!object.bound_overlay || object.bound_overlay.destruction_timer) discover_movable(object, T) + if (!shadower_set) + if (T.below.z_flags & ZM_NO_SHADOW) + T.shadower.color = null + else + T.shadower.color = SHADOWER_DARKENING_COLOR + T.z_queued -= 1 if (T.above) T.above.update_mimic() diff --git a/code/modules/multiz/zmimic/mimic_movable.dm b/code/modules/multiz/zmimic/mimic_movable.dm index 20bf18bbcac..8b9e25398fb 100644 --- a/code/modules/multiz/zmimic/mimic_movable.dm +++ b/code/modules/multiz/zmimic/mimic_movable.dm @@ -80,32 +80,33 @@ return ..() -/atom/movable/openspace/multiplier/proc/copy_lighting(atom/movable/lighting_overlay/LO) +/atom/movable/openspace/multiplier/proc/copy_lighting(atom/movable/lighting_overlay/LO, use_shadower_mult = TRUE) appearance = LO layer = MIMICED_LIGHTING_LAYER plane = OPENTURF_MAX_PLANE blend_mode = BLEND_MULTIPLY set_invisibility(INVISIBILITY_NONE) - if (icon_state == LIGHTING_BASE_ICON_STATE) - // We're using a color matrix, so just darken the colors across the board. - var/list/c_list = color - c_list[CL_MATRIX_RR] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_RG] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_RB] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_GR] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_GG] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_GB] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_BR] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_BG] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_BB] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_AR] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_AG] *= SHADOWER_DARKENING_FACTOR - c_list[CL_MATRIX_AB] *= SHADOWER_DARKENING_FACTOR - color = c_list - else - // Not a color matrix, so we can just use the color var ourselves. - color = SHADOWER_DARKENING_COLOR + if (use_shadower_mult) + if (icon_state == LIGHTING_BASE_ICON_STATE) + // We're using a color matrix, so just darken the colors across the board. + var/list/c_list = color + c_list[CL_MATRIX_RR] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_RG] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_RB] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_GR] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_GG] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_GB] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_BR] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_BG] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_BB] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_AR] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_AG] *= SHADOWER_DARKENING_FACTOR + c_list[CL_MATRIX_AB] *= SHADOWER_DARKENING_FACTOR + color = c_list + else + // Not a color matrix, so we can just use the color var ourselves. + color = SHADOWER_DARKENING_COLOR if (our_overlays || priority_overlays) compile_overlays() From 5049f4fc47d2eaeb0e93551d96b3543d5642ab60 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sat, 3 Feb 2024 15:21:08 -0600 Subject: [PATCH 6/8] zm: Merge OVERRIDE and BASETURF, add TERMINATOR --- code/__defines/zmimic.dm | 8 ++++---- code/controllers/subsystems/zcopy.dm | 24 +++++++++--------------- code/modules/multiz/zmimic/mimic_turf.dm | 2 +- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index 2ee55949e4d..740c662e9b8 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -1,4 +1,4 @@ -#define ZM_DESTRUCTION_TIMER(TARGET) addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, qdel_self)), 10 SECONDS, TIMER_STOPPABLE) +#define ZM_DESTRUCTION_TIMER(TARGET) addtimer(CALLBACK(TARGET, TYPE_PROC_REF(/datum, qdel_self)), 10 SECONDS, TIMER_STOPPABLE) #define TURF_IS_MIMICKING(T) (isturf(T) && (T:z_flags & ZM_MIMIC_BELOW)) #define CHECK_OO_EXISTENCE(OO) if (OO && !MOVABLE_IS_ON_ZTURF(OO) && !OO.destruction_timer) { OO.destruction_timer = ZM_DESTRUCTION_TIMER(OO); } #define UPDATE_OO_IF_PRESENT CHECK_OO_EXISTENCE(bound_overlay); if (bound_overlay) { update_above(); } @@ -30,9 +30,9 @@ #define ZM_ALLOW_ATMOS 8 //! If this turf permits passage of air. #define ZM_MIMIC_NO_AO 16 //! If the turf shouldn't apply regular turf AO and only do Z-mimic AO. #define ZM_NO_OCCLUDE 32 //! Don't occlude below atoms if we're a non-mimic z-turf. -#define ZM_MIMIC_BASETURF 64 //! Mimic baseturf instead of the below atom. Sometimes useful for elevators. -#define ZM_OVERRIDE 128 //! If this turf is being copied, read the `z_appearance` var instead of our real appearance. -#define ZM_NO_SHADOW 256 //! If this turf is being copied, hide the shadower. +#define ZM_OVERRIDE 64 //! Copy only z_appearance or baseturf and bail, do not attempt to copy movables. This is significantly cheaper and allows you to override the mimic, but results in movables not being visible. +#define ZM_NO_SHADOW 128 //! If this turf is being copied, hide the shadower. +#define ZM_TERMINATOR 256 //! Consider this turf the terminus of a Z-group, like the bottom of a Z-group or a ZM_OVERRIDE turf. // Convenience flags. #define ZM_MIMIC_DEFAULTS (ZM_MIMIC_BELOW|ZM_ALLOW_LIGHTING) //! Common defaults for zturfs. diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index f251c6d6e5a..96dabb65f56 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -255,7 +255,7 @@ SUBSYSTEM_DEF(zcopy) if (!T.below) ZM_RECORD_START flush_z_state(T) - if (T.z_flags & ZM_MIMIC_BASETURF) + if (T.z_flags & ZM_OVERRIDE) simple_appearance_copy(T, get_base_turf_by_area(T), OPENTURF_MAX_PLANE) else simple_appearance_copy(T, SSskybox.dust_cache["[((T.x + T.y) ^ ~(T.x * T.y) + T.z) % 25]"]) @@ -287,7 +287,7 @@ SUBSYSTEM_DEF(zcopy) // Get the bottom-most turf, the one we want to mimic. // Baseturf mimics act as false bottoms of the stack. var/turf/Td = T - while (Td.below && !(Td.z_flags & ZM_MIMIC_BASETURF)) + while (Td.below && !(Td.z_flags & (ZM_OVERRIDE|ZM_TERMINATOR))) Td = Td.below // Depth must be the depth of the *visible* turf, not self. @@ -297,9 +297,9 @@ SUBSYSTEM_DEF(zcopy) var/t_target = OPENTURF_MAX_PLANE - turf_depth // This is where the turf (but not the copied atoms) gets put. // Turf is set to mimic baseturf, handle that and bail. - if (T.z_flags & ZM_MIMIC_BASETURF) + if (T.z_flags & ZM_OVERRIDE) flush_z_state(T) - simple_appearance_copy(T, get_base_turf_by_area(T), t_target) + simple_appearance_copy(T, Td.z_appearance || get_base_turf_by_area(T), t_target) if (T.above) T.above.update_mimic() @@ -316,7 +316,7 @@ SUBSYSTEM_DEF(zcopy) break continue - // If we previously were ZM_MIMIC_BASETURF, there might be an orphaned proxy. + // If we previously were ZM_OVERRIDE, there might be an orphaned proxy. else if (T.mimic_underlay) QDEL_NULL(T.mimic_underlay) @@ -325,17 +325,11 @@ SUBSYSTEM_DEF(zcopy) T.z_eventually_space = TRUE t_target = SPACE_PLANE - var/appearance_target - if (T.below.z_flags & ZM_OVERRIDE) - appearance_target = T.below.z_appearance - else - appearance_target = Td - if (T.z_flags & ZM_MIMIC_OVERWRITE) // This openturf doesn't care about its icon, so we can just overwrite it. if (T.below.mimic_proxy) QDEL_NULL(T.below.mimic_proxy) - T.appearance = appearance_target // This used to be T.below rather than Td, not sure why. Legacy artifact? + T.appearance = Td.z_appearance || Td T.name = initial(T.name) T.desc = initial(T.desc) T.gender = initial(T.gender) @@ -346,7 +340,7 @@ SUBSYSTEM_DEF(zcopy) if (!T.below.mimic_proxy) T.below.mimic_proxy = new(T) var/atom/movable/openspace/turf_proxy/TO = T.below.mimic_proxy - TO.appearance = appearance_target + TO.appearance = Td.z_appearance || Td TO.name = T.name TO.gender = T.gender // Need to grab this too so PLURAL works properly in examine. TO.opacity = FALSE @@ -735,8 +729,8 @@ SUBSYSTEM_DEF(zcopy) if (!T.below) out += "

    Using synthetic rendering (Not Z).

    " - else if (T.z_flags & ZM_MIMIC_BASETURF) - out += "

    Using synthetic rendering (BASETURF).

    " + else if (T.z_flags & ZM_OVERRIDE) + out += "

    Using synthetic rendering (OVERRIDE).

    " var/list/found_oo = list(T) var/turf/Tbelow = T diff --git a/code/modules/multiz/zmimic/mimic_turf.dm b/code/modules/multiz/zmimic/mimic_turf.dm index 3bc71a7e6dd..d47230e98e1 100644 --- a/code/modules/multiz/zmimic/mimic_turf.dm +++ b/code/modules/multiz/zmimic/mimic_turf.dm @@ -15,7 +15,7 @@ /// If this Z-turf leads to space, uninterrupted. var/tmp/z_eventually_space = FALSE var/z_flags = 0 - /// If ZM_OVERRIDE is set, use this var for appearance instead of the `appearance` BYOND-var. Anything that's valid in `appearance` is valid here. + /// Use this appearance for our appearance instead of `appearance`. If ZM_OVERRIDE is set, *only* this will be visible, no movables will be copied. var/z_appearance // debug From 579ff4e15a679b98c65feb7d5c8fa3706070ce13 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Tue, 6 Feb 2024 00:58:30 -0600 Subject: [PATCH 7/8] zm: Fix MOVABLE_IS_ON_ZTURF --- code/__defines/zmimic.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/__defines/zmimic.dm b/code/__defines/zmimic.dm index 740c662e9b8..4f2998f1542 100644 --- a/code/__defines/zmimic.dm +++ b/code/__defines/zmimic.dm @@ -17,7 +17,7 @@ ) /// Is this movable located on a turf that is mimicking below? Note: this does not necessarily mean *directly* on. #define MOVABLE_IS_ON_ZTURF(M) (\ - isturf(M:loc) && (TURF_IS_MIMICKING(M:loc:above) \ + (TURF_IS_MIMICKING(M:loc) \ || ((M:z_flags & ZMM_LOOKAHEAD) && ZM_INTERNAL_SCAN_LOOKAHEAD(M, z_flags, ZM_MIMIC_BELOW)) \ || ((M:z_flags & ZMM_LOOKBESIDE) && ZM_INTERNAL_SCAN_LOOKBESIDE(M, z_flags, ZM_MIMIC_BELOW))) \ ) From 86c2bb34ff90c64b323efba5e0268f99c0a9801d Mon Sep 17 00:00:00 2001 From: Lohikar Date: Tue, 6 Feb 2024 01:10:56 -0600 Subject: [PATCH 8/8] zm: Fix null ref runtimes --- code/modules/multiz/zmimic/mimic_movable.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/multiz/zmimic/mimic_movable.dm b/code/modules/multiz/zmimic/mimic_movable.dm index 8b9e25398fb..61b36d1127a 100644 --- a/code/modules/multiz/zmimic/mimic_movable.dm +++ b/code/modules/multiz/zmimic/mimic_movable.dm @@ -175,7 +175,7 @@ destruction_timer = ZM_DESTRUCTION_TIMER(src) /atom/movable/openspace/mimic/proc/reset_internal_layering() - if (bound_overlay.override_depth) + if (bound_overlay?.override_depth) depth = bound_overlay.override_depth else if (isturf(associated_atom.loc)) depth = min(SSzcopy.zlev_maximums[associated_atom.z] - associated_atom.z, OPENTURF_MAX_DEPTH)