diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm index 63ad7655be7..d468be8bf80 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -13,7 +13,13 @@ #define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact" ///signal sent out by an atom upon onZImpact : (turf/impacted_turf, levels) #define COMSIG_ATOM_ON_Z_IMPACT "movable_on_z_impact" -///Signal sent after an atom movable moves on shuttle. +/// From base of /atom/movable/beforeShuttleMove (turf/newT, direction, move_mode, /obj/docking_port/mobile/moving_dock) +#define COMSIG_ATOM_BEFORE_SHUTTLE_MOVE "movable_before_shuttle_move" + // Docking turf movement return values - return a combination of these to override the move_mode for the turf containing the atom + #define COMPONENT_MOVE_TURF MOVE_TURF + #define COMPONENT_MOVE_AREA MOVE_AREA + #define COMPONENT_MOVE_CONTENTS MOVE_CONTENTS +/// From base of /atom/movable/afterShuttleMove (turf/oldT) #define COMSIG_ATOM_AFTER_SHUTTLE_MOVE "movable_after_shuttle_move" ///called on a movable (NOT living) when it starts pulling (atom/movable/pulled, state, force) #define COMSIG_ATOM_START_PULL "movable_start_pull" diff --git a/code/datums/components/usb_port.dm b/code/datums/components/usb_port.dm index 051101fdbb4..c996475a239 100644 --- a/code/datums/components/usb_port.dm +++ b/code/datums/components/usb_port.dm @@ -1,5 +1,11 @@ +/// Range checking is being deferred because the component's parent is being moved by a shuttle +#define PARENT_DEFERRED (1<<0) +/// Range checking is being deferred because the circuit shell being tracked is being moved by a shuttle +#define PHYSICAL_OBJECT_DEFERRED (1<<1) + /// Opens up a USB port that can be connected to by circuits, creating registerable circuit components /datum/component/usb_port + dupe_mode = COMPONENT_DUPE_UNIQUE /// The component types to create when something plugs in var/list/circuit_component_types @@ -18,6 +24,9 @@ /// The current physical object that the beam is connected to and listens to. var/atom/movable/physical_object + /// Used to prevent range checking during shuttle movement, which moves atoms en-masse. + var/defer_range_checks = 0 + /datum/component/usb_port/Initialize(list/circuit_component_types) if (!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -48,6 +57,8 @@ /datum/component/usb_port/RegisterWithParent() RegisterSignal(parent, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, PROC_REF(on_atom_usb_cable_try_attach)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + RegisterSignal(parent, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, PROC_REF(before_parent_shuttle_move)) + RegisterSignal(parent, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, PROC_REF(after_parent_shuttle_move)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_MOVABLE_CIRCUIT_LOADED, PROC_REF(on_load)) @@ -58,6 +69,8 @@ UnregisterSignal(parent, list( COMSIG_ATOM_USB_CABLE_TRY_ATTACH, COMSIG_MOVABLE_MOVED, + COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, + COMSIG_ATOM_AFTER_SHUTTLE_MOVE, COMSIG_ATOM_EXAMINE, COMSIG_MOVABLE_CIRCUIT_LOADED, )) @@ -114,6 +127,8 @@ UnregisterSignal(physical_object, list( COMSIG_MOVABLE_MOVED, + COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, + COMSIG_ATOM_AFTER_SHUTTLE_MOVE, COMSIG_ATOM_EXAMINE, )) @@ -191,6 +206,8 @@ usb_cable_beam = atom_parent.Beam(new_physical_object, "usb_cable_beam", 'icons/obj/science/circuits.dmi') RegisterSignal(new_physical_object, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + RegisterSignal(new_physical_object, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, PROC_REF(before_physical_object_shuttle_move)) + RegisterSignal(new_physical_object, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, PROC_REF(after_physical_object_shuttle_move)) RegisterSignal(new_physical_object, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine_shell)) physical_object = new_physical_object @@ -205,6 +222,9 @@ if (isnull(attached_circuit)) return + if (defer_range_checks) + return + if (IN_GIVEN_RANGE(attached_circuit, parent, USB_CABLE_MAX_RANGE)) return @@ -245,3 +265,28 @@ usb_cable_ref = null QDEL_NULL(usb_cable_beam) + +/datum/component/usb_port/proc/before_parent_shuttle_move() + SIGNAL_HANDLER + + defer_range_checks |= PARENT_DEFERRED + +/datum/component/usb_port/proc/before_physical_object_shuttle_move() + SIGNAL_HANDLER + + defer_range_checks |= PHYSICAL_OBJECT_DEFERRED + +/datum/component/usb_port/proc/after_parent_shuttle_move() + SIGNAL_HANDLER + + defer_range_checks &= ~PARENT_DEFERRED + on_moved() + +/datum/component/usb_port/proc/after_physical_object_shuttle_move() + SIGNAL_HANDLER + + defer_range_checks &= ~PHYSICAL_OBJECT_DEFERRED + on_moved() + +#undef PARENT_DEFERRED +#undef PHYSICAL_OBJECT_DEFERRED diff --git a/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm b/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm index b8f23948bb7..5c812157c9a 100644 --- a/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm +++ b/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm @@ -99,7 +99,8 @@ All ShuttleMove procs go here // returns the new move_mode (based on the old) // WARNING: Do not leave turf contents in beforeShuttleMove or dock() will runtime /atom/movable/proc/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) - return move_mode + SHOULD_CALL_PARENT(TRUE) + return SEND_SIGNAL(src, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, newT, rotation, move_mode, moving_dock) || move_mode /// Called on atoms to move the atom to the new location /atom/movable/proc/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock) @@ -115,6 +116,7 @@ All ShuttleMove procs go here // Called on atoms after everything has been moved /atom/movable/proc/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) + SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, oldT) if(light) update_light() diff --git a/code/modules/wiremod/core/usb_cable.dm b/code/modules/wiremod/core/usb_cable.dm index 62ba799b5b0..791ecab3735 100644 --- a/code/modules/wiremod/core/usb_cable.dm +++ b/code/modules/wiremod/core/usb_cable.dm @@ -14,6 +14,9 @@ /// The currently connected circuit var/obj/item/integrated_circuit/attached_circuit + /// Used to prevent range checking during shuttle movement, which moves atoms en-masse. + var/defer_range_checks = FALSE + /obj/item/usb_cable/Destroy() attached_circuit = null STOP_PROCESSING(SSobj, src) @@ -22,6 +25,12 @@ /obj/item/usb_cable/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + var/static/list/connections = list( + COMSIG_MOVABLE_MOVED = PROC_REF(on_moved), + COMSIG_ATOM_BEFORE_SHUTTLE_MOVE = PROC_REF(before_shuttle_move), + COMSIG_ATOM_AFTER_SHUTTLE_MOVE = PROC_REF(after_shuttle_move), + ) + AddComponent(/datum/component/connect_containers, src, connections) /obj/item/usb_cable/examine(mob/user) . = ..() @@ -29,13 +38,6 @@ if (!isnull(attached_circuit)) . += span_notice("It is attached to [attached_circuit.shell || attached_circuit].") -// Look, I'm not happy about this either, but moving an object doesn't call Moved if it's inside something else. -// There's good reason for this, but there's no element or similar yet to track it as far as I know. -// SSobj runs infrequently, this is only ran while there's an attached circuit, its performance cost is negligible. -/obj/item/usb_cable/process(seconds_per_tick) - if (!check_in_range()) - return PROCESS_KILL - /obj/item/usb_cable/pre_attack(atom/target, mob/living/user, list/modifiers) . = ..() if (.) @@ -47,7 +49,6 @@ var/signal_result = SEND_SIGNAL(target, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, src, user) - var/last_attached_circuit = attached_circuit if (signal_result & COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT) if (isnull(attached_circuit)) CRASH("Producers of COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT must set attached_circuit") @@ -55,13 +56,6 @@ playsound(src, 'sound/machines/pda_button/pda_button1.ogg', 20, TRUE) - if (last_attached_circuit != attached_circuit) - if (!isnull(last_attached_circuit)) - unregister_circuit_signals(last_attached_circuit) - register_circuit_signals() - - START_PROCESSING(SSobj, src) - return TRUE if (signal_result & COMSIG_USB_CABLE_ATTACHED) @@ -86,34 +80,39 @@ user.visible_message(span_suicide("[user] is wrapping [src] around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!")) return OXYLOSS -/obj/item/usb_cable/proc/register_circuit_signals() - RegisterSignal(attached_circuit, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) - RegisterSignal(attached_circuit, COMSIG_QDELETING, PROC_REF(on_circuit_qdeling)) - RegisterSignal(attached_circuit.shell, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) - -/obj/item/usb_cable/proc/unregister_circuit_signals(obj/item/integrated_circuit/old_circuit) - UnregisterSignal(attached_circuit, list( - COMSIG_MOVABLE_MOVED, - COMSIG_QDELETING, - )) - - UnregisterSignal(attached_circuit.shell, COMSIG_MOVABLE_MOVED) - /obj/item/usb_cable/proc/on_moved() SIGNAL_HANDLER + if(defer_range_checks) + return + check_in_range() + +/obj/item/usb_cable/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock) + . = ..() + before_shuttle_move() + +/obj/item/usb_cable/proc/before_shuttle_move() + SIGNAL_HANDLER + + defer_range_checks = TRUE + +/obj/item/usb_cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) + . = ..() + after_shuttle_move() + +/obj/item/usb_cable/proc/after_shuttle_move() + SIGNAL_HANDLER + + defer_range_checks = FALSE check_in_range() /obj/item/usb_cable/proc/check_in_range() if (isnull(attached_circuit)) - STOP_PROCESSING(SSobj, src) return FALSE if (!IN_GIVEN_RANGE(attached_circuit, src, USB_CABLE_MAX_RANGE)) balloon_alert_to_viewers("detached, too far away") - unregister_circuit_signals(attached_circuit) attached_circuit = null - STOP_PROCESSING(SSobj, src) return FALSE return TRUE @@ -122,4 +121,3 @@ SIGNAL_HANDLER attached_circuit = null - STOP_PROCESSING(SSobj, src)