From f0afc3224519a320b4abedf14d1cb8d6e4ccb2d1 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 24 Jun 2026 22:14:33 -0500 Subject: [PATCH 01/12] Revert turf signal preservation --- code/datums/datum.dm | 11 +++------- code/game/machinery/telecomms/presets.dm | 10 ++++++++- code/game/objects/structures/multiz_stairs.dm | 8 ++++++- code/game/turfs/turf.dm | 22 ++++--------------- code/game/turfs/walls/wall_types.dm | 18 +++++++-------- code/modules/cm_aliens/weeds.dm | 6 +---- code/modules/tents/deployed_tents.dm | 10 +++++++-- 7 files changed, 40 insertions(+), 45 deletions(-) diff --git a/code/datums/datum.dm b/code/datums/datum.dm index a4e5b41030ec..51cf9ec48849 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -130,14 +130,6 @@ debug_log("'[src]' datum_components was not null after removing all components! [length(datum_components)] entries remained...") datum_components.Cut() - clear_signal_refs() - //END: ECS SHIT - - return QDEL_HINT_QUEUE - -///Only override this if you know what you're doing. You do not know what you're doing -///This is a threat -/datum/proc/clear_signal_refs() var/list/lookup = comp_lookup if(lookup) for(var/sig in lookup) @@ -152,6 +144,9 @@ for(var/target in signal_procs) UnregisterSignal(target, signal_procs[target]) + //END: ECS SHIT + + return QDEL_HINT_QUEUE /** * Callback called by a timer to end an associative-list-indexed cooldown. diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 1eafc222a52a..62c03efe6d7b 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -220,7 +220,15 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() . = ..() - RegisterSignal(get_turf(src), COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) + register_with_turf() + +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf() + SIGNAL_HANDLER + var/turf/location = get_turf(src) + if(location) + RegisterSignal(location, COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/get_examine_text(mob/user) . = ..() diff --git a/code/game/objects/structures/multiz_stairs.dm b/code/game/objects/structures/multiz_stairs.dm index 1a041cedb363..3e76f50e8cb8 100644 --- a/code/game/objects/structures/multiz_stairs.dm +++ b/code/game/objects/structures/multiz_stairs.dm @@ -5,7 +5,8 @@ /obj/structure/stairs/multiz/Initialize(mapload, ...) . = ..() - RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_turf_entered)) + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) + register_with_turf() for(var/turf/blocked_turf in range(1, src)) blockers += WEAKREF(new /obj/effect/build_blocker(blocked_turf, src)) blockers += WEAKREF(new /obj/structure/blocker/anti_cade(blocked_turf)) @@ -15,6 +16,11 @@ QDEL_LIST(blockers) return ..() +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) +/obj/structure/stairs/multiz/proc/register_with_turf() + SIGNAL_HANDLER + RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_turf_entered)) + /obj/structure/stairs/multiz/proc/on_turf_entered(turf/source, atom/movable/enterer) SIGNAL_HANDLER if(!istype(enterer, /mob)) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index f9ab30019ca1..a491df4145f5 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -358,6 +358,10 @@ return TRUE //Nothing found to block so return success! /turf/Entered(atom/movable/A) + SHOULD_CALL_PARENT(TRUE) + + ..() // Shouldn't do anything but to satisfy lint + if(!istype(A)) return @@ -458,13 +462,6 @@ created_baseturf_lists[new_baseturfs[length(new_baseturfs)]] = new_baseturfs.Copy() return new_baseturfs -/// WARNING WARNING -/// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS -/// It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf -/// We do it because moving signals over was needlessly expensive, and bloated a very commonly used bit of code -/turf/clear_signal_refs() - return - // Creates a new turf // new_baseturfs can be either a single type or list of types, formatted the same as baseturfs. see turf.dm /turf/proc/ChangeTurf(path, list/new_baseturfs, flags) @@ -498,19 +495,8 @@ changing_turf = TRUE qdel(src) //Just get the side effects and call Destroy - // Get signal registrations post-Destroy so stuff that's unregistered on Destroy won't be readded - var/list/old_comp_lookup = comp_lookup?.Copy() - var/list/old_signal_procs = signal_procs?.Copy() var/turf/W = new path(src) - // WARNING WARNING - // Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS - // It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf - if(old_comp_lookup) - LAZYOR(W.comp_lookup, old_comp_lookup) - if(old_signal_procs) - LAZYOR(W.signal_procs, old_signal_procs) - W.weak_reference = old_ref for(var/datum/callback/callback as anything in post_change_callbacks) diff --git a/code/game/turfs/walls/wall_types.dm b/code/game/turfs/walls/wall_types.dm index 7ec978aef332..0c651db79f8b 100644 --- a/code/game/turfs/walls/wall_types.dm +++ b/code/game/turfs/walls/wall_types.dm @@ -1286,7 +1286,8 @@ hivenumber = hive set_hive_data(src, hive) recalculate_structure() - update_tied_turf(loc) + update_tied_turf() + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(update_tied_turf)) RegisterSignal(src, COMSIG_MOVABLE_XENO_START_PULLING, PROC_REF(allow_xeno_drag)) RegisterSignal(src, COMSIG_MOVABLE_PULLED, PROC_REF(continue_allowing_drag)) @@ -1397,20 +1398,17 @@ return ..() -/obj/structure/alien/movable_wall/proc/update_tied_turf(turf/T) - SIGNAL_HANDLER +/obj/structure/alien/movable_wall/proc/update_tied_turf() + SIGNAL_HANDLER // COMSIG_MOVABLE_TURF_ENTERED - if(!T) + if(!loc) return if(tied_turf) - UnregisterSignal(tied_turf, COMSIG_TURF_ENTER) - RegisterSignal(T, COMSIG_TURF_ENTER, PROC_REF(check_for_move)) - tied_turf = T + UnregisterSignal(tied_turf, list(COMSIG_TURF_ENTER)) -/obj/structure/alien/movable_wall/forceMove(atom/dest) - . = ..() - update_tied_turf(loc) + tied_turf = loc + RegisterSignal(loc, COMSIG_TURF_ENTER, PROC_REF(check_for_move)) /obj/structure/alien/movable_wall/proc/check_for_move(turf/T, atom/movable/mover) if(group.next_push > world.time) diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index 3d2b3021a254..488a24e1922e 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -80,7 +80,7 @@ SEND_SIGNAL(turf, COMSIG_WEEDNODE_GROWTH) // Currently for weed_food wakeup RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(set_turf_weeded)) - RegisterSignal(turf, COMSIG_PRE_TURF_CHANGE, PROC_REF(pre_turf_change)) + if(hivenumber == XENO_HIVE_NORMAL) RegisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING, PROC_REF(forsaken_handling)) @@ -95,10 +95,6 @@ T.weeds = src -// Before the turf changes, register a temporary callback to update `weeds` post-change. -/obj/effect/alien/weeds/proc/pre_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) - post_change_callbacks += CALLBACK(src, PROC_REF(set_turf_weeded), source) - /obj/effect/alien/weeds/proc/forsaken_handling() SIGNAL_HANDLER if(is_ground_level(z)) diff --git a/code/modules/tents/deployed_tents.dm b/code/modules/tents/deployed_tents.dm index 1d386bf28256..11776f10a661 100644 --- a/code/modules/tents/deployed_tents.dm +++ b/code/modules/tents/deployed_tents.dm @@ -27,8 +27,8 @@ . = ..() bound_width = x_dim * world.icon_size bound_height = y_dim * world.icon_size - for(var/turf/turf in locs) - RegisterSignal(turf, COMSIG_TURF_ENTERED, PROC_REF(movable_entering_tent), override = TRUE) + RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_turf_signals)) + register_turf_signals() switch(SSmapping.configs[GROUND_MAP].camouflage_type) if("jungle") @@ -46,6 +46,12 @@ roof_image.appearance_flags = KEEP_APART src.overlays += roof_image +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) +/obj/structure/tent/proc/register_turf_signals() + SIGNAL_HANDLER + for(var/turf/turf in locs) + RegisterSignal(turf, COMSIG_TURF_ENTERED, PROC_REF(movable_entering_tent), override = TRUE) + /obj/structure/tent/proc/movable_entering_tent(turf/hooked, atom/movable/subject) SIGNAL_HANDLER if(!ismob(subject)) From cd59bf825611ea07a433a04f459f81a12c2f5436 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 24 Jun 2026 22:33:18 -0500 Subject: [PATCH 02/12] weed_food --- code/datums/components/weed_food.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index e2f0d0b46a63..e0d08c922e16 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -87,7 +87,7 @@ parent_buckle = null /datum/component/weed_food/RegisterWithParent() - RegisterSignal(parent_mob, list(COMSIG_MOVABLE_MOVED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE), PROC_REF(on_move)) + RegisterSignal(parent_mob, list(COMSIG_MOVABLE_TURF_ENTERED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE), PROC_REF(on_move)) RegisterSignal(parent_mob, list(COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED), PROC_REF(on_rejuv)) RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(on_update)) RegisterSignal(parent_mob, COMSIG_LIVING_PREIGNITION, PROC_REF(on_preignition)) @@ -98,7 +98,7 @@ /datum/component/weed_food/UnregisterFromParent() if(parent_mob) UnregisterSignal(parent_mob, list( - COMSIG_MOVABLE_MOVED, + COMSIG_MOVABLE_TURF_ENTERED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED, @@ -115,7 +115,7 @@ UnregisterSignal(parent_nest, COMSIG_PARENT_QDELETING) UnregisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING) -/// SIGNAL_HANDLER for COMSIG_MOVABLE_MOVED and COMSIG_ATOM_AFTER_SHUTTLE_MOVE +/// SIGNAL_HANDLER for COMSIG_MOVABLE_TURF_ENTERED and COMSIG_ATOM_AFTER_SHUTTLE_MOVE /datum/component/weed_food/proc/on_move() SIGNAL_HANDLER From ad434263c27fb3bb2ebbde4604a9f6d0916f2571 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 24 Jun 2026 23:03:47 -0500 Subject: [PATCH 03/12] Entered is delayed for mapload (tents are always maploaded though) --- code/game/machinery/telecomms/presets.dm | 5 +++-- code/game/objects/structures/multiz_stairs.dm | 3 ++- code/game/turfs/walls/wall_types.dm | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 62c03efe6d7b..4c7644c27118 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -218,10 +218,11 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /// Holds the delay for when a cluster can recorrupt the comms tower after a pylon has been destroyed COOLDOWN_DECLARE(corruption_delay) -/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize(mapload, ...) . = ..() RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) - register_with_turf() + if(!mapload) + register_with_turf() /// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf() diff --git a/code/game/objects/structures/multiz_stairs.dm b/code/game/objects/structures/multiz_stairs.dm index 3e76f50e8cb8..09e7db08ae3a 100644 --- a/code/game/objects/structures/multiz_stairs.dm +++ b/code/game/objects/structures/multiz_stairs.dm @@ -6,7 +6,8 @@ /obj/structure/stairs/multiz/Initialize(mapload, ...) . = ..() RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) - register_with_turf() + if(!mapload) + register_with_turf() for(var/turf/blocked_turf in range(1, src)) blockers += WEAKREF(new /obj/effect/build_blocker(blocked_turf, src)) blockers += WEAKREF(new /obj/structure/blocker/anti_cade(blocked_turf)) diff --git a/code/game/turfs/walls/wall_types.dm b/code/game/turfs/walls/wall_types.dm index 0c651db79f8b..6f78f0bcc8fb 100644 --- a/code/game/turfs/walls/wall_types.dm +++ b/code/game/turfs/walls/wall_types.dm @@ -1286,7 +1286,8 @@ hivenumber = hive set_hive_data(src, hive) recalculate_structure() - update_tied_turf() + if(!mapload) + update_tied_turf() RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(update_tied_turf)) RegisterSignal(src, COMSIG_MOVABLE_XENO_START_PULLING, PROC_REF(allow_xeno_drag)) RegisterSignal(src, COMSIG_MOVABLE_PULLED, PROC_REF(continue_allowing_drag)) From d7f4f4bd20891b7c5a9e0124aac2cb2e38614a1b Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 24 Jun 2026 23:23:58 -0500 Subject: [PATCH 04/12] Fix stairs not handling turf changes around it --- code/game/objects/structures/multiz_stairs.dm | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/code/game/objects/structures/multiz_stairs.dm b/code/game/objects/structures/multiz_stairs.dm index 09e7db08ae3a..2dbce845edf6 100644 --- a/code/game/objects/structures/multiz_stairs.dm +++ b/code/game/objects/structures/multiz_stairs.dm @@ -20,9 +20,9 @@ /// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) /obj/structure/stairs/multiz/proc/register_with_turf() SIGNAL_HANDLER - RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_turf_entered)) + RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_stairs_moved)) -/obj/structure/stairs/multiz/proc/on_turf_entered(turf/source, atom/movable/enterer) +/obj/structure/stairs/multiz/proc/on_stairs_moved(turf/source, atom/movable/enterer) SIGNAL_HANDLER if(!istype(enterer, /mob)) return @@ -150,8 +150,21 @@ LAZYADD(from_turf_to_images[from_turf], destination_turf_images[to_turf]) break // we found stairs that work, go on to the next turf if(length(from_turf_to_images[from_turf])) - RegisterSignal(from_turf, COMSIG_TURF_ENTERED, PROC_REF(handle_entered), TRUE) + RegisterSignal(from_turf, COMSIG_TURF_ENTERED, PROC_REF(handle_entered), override=TRUE) + RegisterSignal(from_turf, COMSIG_PRE_TURF_CHANGE, PROC_REF(handle_pre_turf_change), override=TRUE) +/// Handler for COMSIG_PRE_TURF_CHANGE to set post_change_callbacks +/datum/staircase/proc/handle_pre_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) + SIGNAL_HANDLER + post_change_callbacks += CALLBACK(src, PROC_REF(re_register_from_turf_signals), source) + +/// Re-registers the COMSIG_TURF_ENTERED and COMSIG_PRE_TURF_CHANGE for handle_pre_turf_change +/datum/staircase/proc/re_register_from_turf_signals(turf/new_turf) + SHOULD_NOT_SLEEP(TRUE) + RegisterSignal(new_turf, COMSIG_TURF_ENTERED, PROC_REF(handle_entered)) + RegisterSignal(new_turf, COMSIG_PRE_TURF_CHANGE, PROC_REF(handle_pre_turf_change)) + +/// Handles COMSIG_TURF_ENTERED for mobs that enters a from_turf to register handle_movement and handle_deleted /datum/staircase/proc/handle_entered(turf/originator, atom/what_did_it) SIGNAL_HANDLER @@ -168,7 +181,7 @@ in_range_mob += mover - +/// Handles COMSIG_MOVABLE_MOVED for mobs that were in a from_turf /datum/staircase/proc/handle_movement(mob/mover, old_loc, direction) SIGNAL_HANDLER @@ -187,6 +200,7 @@ in_range_mob -= mover UnregisterSignal(mover, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) +/// Handles COMSIG_PARENT_QDELETING for mobs that were in a from_turf /datum/staircase/proc/handle_deleted(atom/updater) SIGNAL_HANDLER From b8918b878f6b5ea413a32181cd232dda26ef0fee Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 25 Jun 2026 22:44:29 -0500 Subject: [PATCH 05/12] ignore other locs for tcoms --- code/game/machinery/telecomms/presets.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 4c7644c27118..4c362c88ed4a 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -225,10 +225,10 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) register_with_turf() /// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) -/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf() +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf(atom/movable/source, turf/new_turf) SIGNAL_HANDLER var/turf/location = get_turf(src) - if(location) + if(location && (!new_turf || location == new_turf)) // We only need to monitor our loc not our locs RegisterSignal(location, COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/get_examine_text(mob/user) From e7a1ca6f4a46602ea31b993f6347beab69f55d5d Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 25 Jun 2026 23:02:46 -0500 Subject: [PATCH 06/12] More descriptive autodoc for signal --- code/__DEFINES/dcs/signals/atom/signals_turf.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/__DEFINES/dcs/signals/atom/signals_turf.dm b/code/__DEFINES/dcs/signals/atom/signals_turf.dm index 9528609851a8..4e13ae68a629 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_turf.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_turf.dm @@ -1,4 +1,5 @@ -///from /turf/Entered +/// From /turf/Entered(): (turf/entered_turf) +/// NOTE: This will occur for all locs including when turf/ChangeTurf() has New'd a turf #define COMSIG_MOVABLE_TURF_ENTERED "movable_turf_entered" /// from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/post_change_callbacks). From 2c7d5d4519197f4bf7a08a1c2b0c82f2decebc5a Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 25 Jun 2026 23:16:12 -0500 Subject: [PATCH 07/12] Fix open_space logic not calling Entered --- code/controllers/subsystem/hijack.dm | 7 ++----- code/game/turfs/open_space.dm | 7 ++++++- code/game/turfs/turf.dm | 6 ++++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/code/controllers/subsystem/hijack.dm b/code/controllers/subsystem/hijack.dm index b9daf9c2e9ca..d66c5002795e 100644 --- a/code/controllers/subsystem/hijack.dm +++ b/code/controllers/subsystem/hijack.dm @@ -973,12 +973,9 @@ SUBSYSTEM_DEF(hijack) target = target.ChangeTurf(make_current_walkable_type) return target - // Make target open_space and chuck stuff down + // Make target open_space (which will chuck stuff down) var/turf/open_space/space = target.ChangeTurf(/turf/open_space) - for(var/atom/movable/thing in space) - if(istype(thing, /obj/vis_contents_holder)) - continue - space.check_fall(thing) + return space //~~~~~~~~~~~~~~~~~~~~~~~~ FTL STUFF ~~~~~~~~~~~~~~~~~~~~~~~~// diff --git a/code/game/turfs/open_space.dm b/code/game/turfs/open_space.dm index dfbffbc77c2d..9a51152448ac 100644 --- a/code/game/turfs/open_space.dm +++ b/code/game/turfs/open_space.dm @@ -16,7 +16,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr plane = OPEN_SPACE_PLANE_START is_weedable = NOT_WEEDABLE -/turf/open_space/Initialize() +/turf/open_space/Initialize(mapload, ...) pass_flags = GLOB.pass_flags_cache[type] if (isnull(pass_flags)) @@ -27,6 +27,11 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr initialize_pass_flags() ADD_TRAIT(src, TURF_Z_TRANSPARENT_TRAIT, TRAIT_SOURCE_INHERENT) + + // We don't call parent and this is important + for(var/atom/movable/thing in src) + Entered(thing) + return INITIALIZE_HINT_LATELOAD /turf/open_space/Enter(atom/movable/mover, atom/forget) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index a491df4145f5..6449e5160fe3 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -105,8 +105,9 @@ else initialize_pass_flags() - for(var/atom/movable/AM in src) - Entered(AM) + // Be sure to do this if you don't call parent! + for(var/atom/movable/thing in src) + Entered(thing) if(light_power && light_range) update_light() @@ -131,6 +132,7 @@ vis_flags = VIS_HIDE mouse_opacity = MOUSE_OPACITY_TRANSPARENT anchored = TRUE + flags_atom = NO_ZFALL /obj/vis_contents_holder/Initialize(mapload, vis, offset) . = ..() From e9667f9d591e0b1c9b6e2ac583f99a6d37e0f3c2 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 25 Jun 2026 23:31:08 -0500 Subject: [PATCH 08/12] No trying to fall through the world please --- code/game/turfs/open_space.dm | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/code/game/turfs/open_space.dm b/code/game/turfs/open_space.dm index 9a51152448ac..a24c711767db 100644 --- a/code/game/turfs/open_space.dm +++ b/code/game/turfs/open_space.dm @@ -28,6 +28,14 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr ADD_TRAIT(src, TURF_Z_TRANSPARENT_TRAIT, TRAIT_SOURCE_INHERENT) + #ifndef UNIT_TESTS + var/turf/below = get_turf_below() + while(istype(below, /turf/open_space)) + below = SSmapping.get_turf_below(below) + if(!below) + stack_trace("[src] at [COORD(src)] falls through the world!") + #endif + // We don't call parent and this is important for(var/atom/movable/thing in src) Entered(thing) @@ -97,6 +105,13 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr grabbing.grabbed_thing.forceMove(user.loc) climb_down_time *= 1.2 + var/turf/below = get_turf_below() + while(istype(below, /turf/open_space)) + below = SSmapping.get_turf_below(below) + if(!below) + to_chat(user, SPAN_WARNING("You can't go that way.")) + return + if(hands_full) to_chat(user, SPAN_INFO("Trying to climb with your hands full is slowing you down.")) @@ -106,15 +121,10 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr user.visible_message(SPAN_WARNING("[user] climbs down."), SPAN_WARNING("You climb down.")) - var/turf/below = get_turf_below() - while(istype(below, /turf/open_space)) - below = SSmapping.get_turf_below(below) - user.forceMove(below) for(var/atom/movable/thing as anything in grabbed_things) // grabbed things aren't moved to the tile immediately to: make the animation better, preserve the grab thing.forceMove(below) below.on_climb_down(user) - return /turf/open_space/proc/check_fall(atom/movable/movable, kill_if_blocked=TRUE) if(movable.flags_atom & NO_ZFALL) @@ -126,6 +136,9 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr below = SSmapping.get_turf_below(below) height++ + if(!below) + return + movable.forceMove(below) movable.onZImpact(below, height) From e08f9aae783da6678bc98670e9c20f2a0880d771 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 25 Jun 2026 23:45:51 -0500 Subject: [PATCH 09/12] Actually lets assert open_space placement when testing --- code/game/turfs/open_space.dm | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/code/game/turfs/open_space.dm b/code/game/turfs/open_space.dm index a24c711767db..bf3e278ca16e 100644 --- a/code/game/turfs/open_space.dm +++ b/code/game/turfs/open_space.dm @@ -28,12 +28,14 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr ADD_TRAIT(src, TURF_Z_TRANSPARENT_TRAIT, TRAIT_SOURCE_INHERENT) - #ifndef UNIT_TESTS - var/turf/below = get_turf_below() - while(istype(below, /turf/open_space)) - below = SSmapping.get_turf_below(below) - if(!below) - stack_trace("[src] at [COORD(src)] falls through the world!") + #if defined(UNIT_TESTS) || defined(TESTING) + // Assert when testing that this open_space is placed somewhere valid + if(!istype(get_area(src), /area/misc/testroom)) + var/turf/below = get_turf_below() + while(istype(below, /turf/open_space)) + below = SSmapping.get_turf_below(below) + if(!below) + stack_trace("[src] at [COORD(src)] falls through the world!") #endif // We don't call parent and this is important From 50411451aefb3bbdb05b6beb0d1098318705a180 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Mon, 29 Jun 2026 21:17:50 -0500 Subject: [PATCH 10/12] Even moar comments --- code/__DEFINES/dcs/signals/atom/signals_turf.dm | 14 +++++++++----- code/datums/components/weed_food.dm | 1 + code/game/machinery/telecomms/presets.dm | 3 ++- code/game/objects/structures/multiz_stairs.dm | 3 ++- code/game/turfs/walls/wall_types.dm | 1 + code/modules/cm_aliens/weeds.dm | 1 + code/modules/tents/deployed_tents.dm | 7 +++++-- 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/code/__DEFINES/dcs/signals/atom/signals_turf.dm b/code/__DEFINES/dcs/signals/atom/signals_turf.dm index 4e13ae68a629..c5ecca7d876f 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_turf.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_turf.dm @@ -1,10 +1,14 @@ -/// From /turf/Entered(): (turf/entered_turf) -/// NOTE: This will occur for all locs including when turf/ChangeTurf() has New'd a turf +/** + * From /turf/Entered(): (turf/entered_turf) + * NOTE: This will occur for all locs including during turf/ChangeTurf() once Initialize occurs (mapload may delay it) + */ #define COMSIG_MOVABLE_TURF_ENTERED "movable_turf_entered" -/// from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/post_change_callbacks). -/// `post_change_callbacks` is a list that signal handlers can mutate to append `/datum/callback` objects. -/// They will be called with the new turf after the turf has changed. +/** + * From base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/post_change_callbacks) + * `post_change_callbacks` is a list that signal handlers can mutate to append `/datum/callback` objects. + * They will be called with the new turf after the turf has changed (but the turf's Initialize may not have occured yet for mapload). + */ #define COMSIG_PRE_TURF_CHANGE "pre_turf_change" #define COMSIG_TURF_ENTER "turf_enter" diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index e0d08c922e16..da43f6ffe411 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -87,6 +87,7 @@ parent_buckle = null /datum/component/weed_food/RegisterWithParent() + // COMSIG_MOVABLE_TURF_ENTERED to handle movement and ChangeTurf RegisterSignal(parent_mob, list(COMSIG_MOVABLE_TURF_ENTERED, COMSIG_ATOM_AFTER_SHUTTLE_MOVE), PROC_REF(on_move)) RegisterSignal(parent_mob, list(COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED), PROC_REF(on_rejuv)) RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(on_update)) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 4c362c88ed4a..b3b344c87787 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -220,11 +220,12 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize(mapload, ...) . = ..() + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) if(!mapload) register_with_turf() -/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED (turf changed) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf(atom/movable/source, turf/new_turf) SIGNAL_HANDLER var/turf/location = get_turf(src) diff --git a/code/game/objects/structures/multiz_stairs.dm b/code/game/objects/structures/multiz_stairs.dm index 2dbce845edf6..4728182bd3ab 100644 --- a/code/game/objects/structures/multiz_stairs.dm +++ b/code/game/objects/structures/multiz_stairs.dm @@ -5,6 +5,7 @@ /obj/structure/stairs/multiz/Initialize(mapload, ...) . = ..() + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_with_turf)) if(!mapload) register_with_turf() @@ -17,7 +18,7 @@ QDEL_LIST(blockers) return ..() -/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED (turf changed) /obj/structure/stairs/multiz/proc/register_with_turf() SIGNAL_HANDLER RegisterSignal(loc, COMSIG_TURF_ENTERED, PROC_REF(on_stairs_moved)) diff --git a/code/game/turfs/walls/wall_types.dm b/code/game/turfs/walls/wall_types.dm index 6f78f0bcc8fb..5e14aae26f95 100644 --- a/code/game/turfs/walls/wall_types.dm +++ b/code/game/turfs/walls/wall_types.dm @@ -1288,6 +1288,7 @@ recalculate_structure() if(!mapload) update_tied_turf() + // COMSIG_MOVABLE_TURF_ENTERED to handle movement and ChangeTurf RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(update_tied_turf)) RegisterSignal(src, COMSIG_MOVABLE_XENO_START_PULLING, PROC_REF(allow_xeno_drag)) RegisterSignal(src, COMSIG_MOVABLE_PULLED, PROC_REF(continue_allowing_drag)) diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index 488a24e1922e..67a7033b9fef 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -79,6 +79,7 @@ weeded_turf = turf SEND_SIGNAL(turf, COMSIG_WEEDNODE_GROWTH) // Currently for weed_food wakeup + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(set_turf_weeded)) if(hivenumber == XENO_HIVE_NORMAL) diff --git a/code/modules/tents/deployed_tents.dm b/code/modules/tents/deployed_tents.dm index 11776f10a661..b1df28cbf3cf 100644 --- a/code/modules/tents/deployed_tents.dm +++ b/code/modules/tents/deployed_tents.dm @@ -27,6 +27,7 @@ . = ..() bound_width = x_dim * world.icon_size bound_height = y_dim * world.icon_size + // COMSIG_MOVABLE_TURF_ENTERED to handle ChangeTurf RegisterSignal(src, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(register_turf_signals)) register_turf_signals() @@ -46,7 +47,7 @@ roof_image.appearance_flags = KEEP_APART src.overlays += roof_image -/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED if we're moved (turf changed) +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED (turf changed) /obj/structure/tent/proc/register_turf_signals() SIGNAL_HANDLER for(var/turf/turf in locs) @@ -59,7 +60,7 @@ var/mob/subject_mob = subject - + // COMSIG_MOVABLE_TURF_ENTERED to handle movement and ChangeTurf RegisterSignal(subject_mob, list(COMSIG_MOVABLE_TURF_ENTERED, COMSIG_GHOST_MOVED), PROC_REF(mob_moved), override = TRUE) // Must override because we can't know if mob was already inside tent without keeping an awful ref list subject_mob.RegisterSignal(src, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/mob, tent_deletion_clean_up), override = TRUE) @@ -72,10 +73,12 @@ if(ishuman(subject)) RegisterSignal(subject, COMSIG_HUMAN_COLD_PROTECTION_APPLY_MODIFIERS, PROC_REF(cold_protection), override = TRUE) +/// Handler for callback of COMSIG_HUMAN_COLD_PROTECTION_APPLY_MODIFIERS /obj/structure/tent/proc/cold_protection(mob/source, list/protection_data) SIGNAL_HANDLER protection_data["protection"] += cold_protection_factor +/// Handler for callback of COMSIG_MOVABLE_TURF_ENTERED and COMSIG_GHOST_MOVED /obj/structure/tent/proc/mob_moved(mob/subject, turf/target_turf) SIGNAL_HANDLER From ff6bdc6c9d8a8e92b073828ceb85dbbdc053d2bd Mon Sep 17 00:00:00 2001 From: Drulikar Date: Mon, 29 Jun 2026 21:40:18 -0500 Subject: [PATCH 11/12] MOAR --- code/__DEFINES/_click.dm | 2 +- code/__DEFINES/dcs/signals/atom/signals_turf.dm | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/code/__DEFINES/_click.dm b/code/__DEFINES/_click.dm index 1ee40b497ded..25e69f5a988d 100644 --- a/code/__DEFINES/_click.dm +++ b/code/__DEFINES/_click.dm @@ -39,7 +39,7 @@ //Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]") #define SCREEN_LOC "screen-loc" -//Click catcher e.g. /atom/moveable/screen/click_catcher +//Click catcher e.g. /atom/movable/screen/click_catcher #define CLICK_CATCHER "click_catcher" #define CLICK_CATCHER_ADD_PARAM ";click_catcher=1" diff --git a/code/__DEFINES/dcs/signals/atom/signals_turf.dm b/code/__DEFINES/dcs/signals/atom/signals_turf.dm index c5ecca7d876f..7fcffb9e07de 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_turf.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_turf.dm @@ -14,6 +14,11 @@ #define COMSIG_TURF_ENTER "turf_enter" #define COMPONENT_TURF_ALLOW_MOVEMENT (1<<0) #define COMPONENT_TURF_DENY_MOVEMENT (1<<1) + +/** + * From /turf/Entered(): (atom/movable/entered_movable) + * NOTE: This cannot detect a turf/ChangeTurf() because signals are not retained during a ChangeTurf. + */ #define COMSIG_TURF_ENTERED "turf_entered" /// Called when a bullet hits a turf From 5ca8655094068012565b4a399c2a55f74729d848 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Mon, 29 Jun 2026 22:14:59 -0500 Subject: [PATCH 12/12] Move movement check before visible message --- code/game/turfs/open_space.dm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/game/turfs/open_space.dm b/code/game/turfs/open_space.dm index bf3e278ca16e..db41a33420e6 100644 --- a/code/game/turfs/open_space.dm +++ b/code/game/turfs/open_space.dm @@ -85,6 +85,15 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr to_chat(user, SPAN_WARNING("It would be too dangerous to go that way.")) return + var/turf/below = get_turf_below() + while(istype(below, /turf/open_space)) + below = SSmapping.get_turf_below(below) + if(!below) + to_chat(user, SPAN_WARNING("You can't go that way.")) + return + + user.visible_message(SPAN_WARNING("[user] starts climbing down."), SPAN_WARNING("You start climbing down.")) + var/climb_down_time = 1 SECONDS if(ishuman_strict(user)) climb_down_time = 2.5 SECONDS @@ -95,8 +104,6 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr else climb_down_time = 1 SECONDS - user.visible_message(SPAN_WARNING("[user] starts climbing down."), SPAN_WARNING("You start climbing down.")) - var/list/grabbed_things = list() var/hands_full = FALSE for(var/obj/item/in_hand in list(user.l_hand, user.r_hand)) @@ -107,13 +114,6 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr grabbing.grabbed_thing.forceMove(user.loc) climb_down_time *= 1.2 - var/turf/below = get_turf_below() - while(istype(below, /turf/open_space)) - below = SSmapping.get_turf_below(below) - if(!below) - to_chat(user, SPAN_WARNING("You can't go that way.")) - return - if(hands_full) to_chat(user, SPAN_INFO("Trying to climb with your hands full is slowing you down."))