diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm index 4d0913f6765..fb9dc00ddf3 100644 --- a/code/__DEFINES/dcs/flags.dm +++ b/code/__DEFINES/dcs/flags.dm @@ -16,6 +16,9 @@ * The arguments are the same when the text and number values are the same and all other values have the same ref */ #define ELEMENT_BESPOKE (1 << 1) +/// Causes all detach arguments to be passed to detach instead of only being used to identify the element +/// When this is used your Detach proc should have the same signature as your Attach proc +#define ELEMENT_COMPLEX_DETACH (1 << 2) // How multiple components of the exact same type are handled in the same datum /// old component is deleted (default) diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm index 38ae5b3a998..67b75fb0eb3 100644 --- a/code/datums/elements/_element.dm +++ b/code/datums/elements/_element.dm @@ -26,7 +26,7 @@ RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE) /// Deactivates the functionality defines by the element on the given datum -/datum/element/proc/Detach(datum/source, force) +/datum/element/proc/Detach(datum/source, ...) SIGNAL_HANDLER SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src) @@ -54,4 +54,8 @@ */ /datum/proc/_RemoveElement(list/arguments) var/datum/element/ele = SSdcs.GetElement(arguments) - ele.Detach(src) + if(ele.element_flags & ELEMENT_COMPLEX_DETACH) + arguments[1] = src + ele.Detach(arglist(arguments)) + else + ele.Detach(src) diff --git a/code/datums/elements/atmos_sensitive.dm b/code/datums/elements/atmos_sensitive.dm index 44ce01a6e76..e052bc6798c 100644 --- a/code/datums/elements/atmos_sensitive.dm +++ b/code/datums/elements/atmos_sensitive.dm @@ -14,7 +14,7 @@ RegisterSignal(to_track, COMSIG_MOVABLE_MOVED, .proc/handle_move) return ..() -/datum/element/atmos_sensitive/Detach(datum/source, force) +/datum/element/atmos_sensitive/Detach(datum/source) var/atom/us = source us.UnregisterSignal(get_turf(us), COMSIG_TURF_EXPOSE) if(us.flags_1 & ATMOS_IS_PROCESSING_1) diff --git a/code/datums/elements/backblast.dm b/code/datums/elements/backblast.dm index 22a3c434599..903704c159c 100644 --- a/code/datums/elements/backblast.dm +++ b/code/datums/elements/backblast.dm @@ -29,7 +29,7 @@ else RegisterSignal(target, COMSIG_GUN_FIRED, .proc/gun_fired) -/datum/element/backblast/Detach(datum/source, force) +/datum/element/backblast/Detach(datum/source) if(source) UnregisterSignal(source, COMSIG_GUN_FIRED) return ..() diff --git a/code/datums/elements/beauty.dm b/code/datums/elements/beauty.dm index 3d69f313280..937800876e6 100644 --- a/code/datums/elements/beauty.dm +++ b/code/datums/elements/beauty.dm @@ -49,7 +49,7 @@ old_area.totalbeauty -= beauty * beauty_counter[source] old_area.update_beauty() -/datum/element/beauty/Detach(datum/source, force) +/datum/element/beauty/Detach(datum/source) if(!beauty_counter[source]) return ..() var/area/current_area = get_area(source) diff --git a/code/datums/elements/climbable.dm b/code/datums/elements/climbable.dm index 1f50665101e..848dcea376e 100644 --- a/code/datums/elements/climbable.dm +++ b/code/datums/elements/climbable.dm @@ -23,7 +23,7 @@ RegisterSignal(target, COMSIG_MOUSEDROPPED_ONTO, .proc/mousedrop_receive) RegisterSignal(target, COMSIG_ATOM_BUMPED, .proc/try_speedrun) -/datum/element/climbable/Detach(datum/target, force) +/datum/element/climbable/Detach(datum/target) UnregisterSignal(target, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_PARENT_EXAMINE, COMSIG_MOUSEDROPPED_ONTO, COMSIG_ATOM_BUMPED)) return ..() diff --git a/code/datums/elements/connect_loc.dm b/code/datums/elements/connect_loc.dm index fed672239f0..adfcf87233d 100644 --- a/code/datums/elements/connect_loc.dm +++ b/code/datums/elements/connect_loc.dm @@ -1,8 +1,8 @@ /// This element hooks a signal onto the loc the current object is on. /// When the object moves, it will unhook the signal and rehook it to the new object. /datum/element/connect_loc - element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH - id_arg_index = 2 + element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH | ELEMENT_COMPLEX_DETACH + id_arg_index = 3 /// An assoc list of signal -> procpath to register to the loc this object is on. var/list/connections @@ -10,56 +10,71 @@ /// An assoc list of locs that are being occupied and a list of targets that occupy them. var/list/targets = list() -/datum/element/connect_loc/Attach(datum/target, list/connections) + /// The callback used when the turf under the tracked object changes + var/datum/callback/changeturf_callback + +/datum/element/connect_loc/New() . = ..() - if (!ismovable(target)) + changeturf_callback = CALLBACK(src, .proc/post_turf_change) + +/datum/element/connect_loc/Attach(datum/listener, atom/movable/tracked, list/connections) + . = ..() + if (!istype(tracked)) return ELEMENT_INCOMPATIBLE src.connections = connections - RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/on_moved) - update_signals(target) -/datum/element/connect_loc/Detach(datum/source, force) + RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, .proc/on_moved) + update_signals(listener, tracked) + +/datum/element/connect_loc/Detach(datum/listener, atom/movable/tracked, list/connections) . = ..() - if (!ismovable(source)) + if(!tracked) + tracked = listener + + if(!istype(tracked)) return - var/atom/movable/movable_source = source + if (!isnull(tracked.loc)) + unregister_signals(listener, tracked, tracked.loc) - if (!isnull(movable_source.loc)) - unregister_signals(source, movable_source.loc) + UnregisterSignal(tracked, COMSIG_MOVABLE_MOVED) -/datum/element/connect_loc/proc/update_signals(atom/movable/target) - if (isnull(target.loc)) +/datum/element/connect_loc/proc/update_signals(datum/listener, atom/movable/tracked) + var/existing = length(targets[tracked.loc]) + LAZYSET(targets[tracked.loc], tracked, listener) + + if (isnull(tracked.loc)) return - LAZYSET(targets[target.loc], target, TRUE) - for (var/signal in connections) - target.RegisterSignal(target.loc, signal, connections[signal]) + listener.RegisterSignal(tracked.loc, signal, connections[signal]) - if (isturf(target.loc) && length(targets[target.loc]) == 1) - RegisterSignal(target.loc, COMSIG_TURF_CHANGE, .proc/on_turf_change) + if (!existing && isturf(tracked.loc)) + RegisterSignal(tracked.loc, COMSIG_TURF_CHANGE, .proc/on_turf_change) -/datum/element/connect_loc/proc/unregister_signals(atom/movable/target, atom/old_loc) - targets[old_loc] -= target +/datum/element/connect_loc/proc/unregister_signals(datum/listener, atom/movable/tracked, atom/old_loc) + targets[old_loc] -= tracked if (length(targets[old_loc]) == 0) targets -= old_loc - for (var/signal in connections) - target.UnregisterSignal(old_loc, signal) + // Yes this is after the above because we use null as a key when objects are in nullspace + if(isnull(old_loc)) + return - if (isturf(old_loc) && !(target.loc in targets)) + for (var/signal in connections) + listener.UnregisterSignal(old_loc, signal) + + if (!targets[old_loc] && isturf(old_loc)) UnregisterSignal(old_loc, COMSIG_TURF_CHANGE) -/datum/element/connect_loc/proc/on_moved(atom/movable/source, atom/old_loc) +/datum/element/connect_loc/proc/on_moved(atom/movable/tracked, atom/old_loc) SIGNAL_HANDLER - if (!isnull(old_loc)) - unregister_signals(source, old_loc) - - update_signals(source) + var/datum/listener = targets[old_loc][tracked] + unregister_signals(listener, tracked, old_loc) + update_signals(listener, tracked) /datum/element/connect_loc/proc/on_turf_change( turf/source, @@ -70,10 +85,9 @@ ) SIGNAL_HANDLER - post_change_callbacks += CALLBACK(src, .proc/post_turf_change) + post_change_callbacks += changeturf_callback /datum/element/connect_loc/proc/post_turf_change(turf/new_turf) - SHOULD_NOT_SLEEP(TRUE) - - for (var/atom/movable/target as anything in targets[new_turf]) - update_signals(target) + for (var/atom/movable/tracked as anything in targets[new_turf]) + var/datum/listener = targets[new_turf][tracked] + update_signals(listener, tracked) diff --git a/code/datums/elements/decal.dm b/code/datums/elements/decal.dm index dbd0228b2a2..500a0264267 100644 --- a/code/datums/elements/decal.dm +++ b/code/datums/elements/decal.dm @@ -92,7 +92,7 @@ pic.alpha = _alpha return TRUE -/datum/element/decal/Detach(atom/source, force) +/datum/element/decal/Detach(atom/source) UnregisterSignal(source, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_TURF_ON_SHUTTLE_MOVE)) source.update_appearance() if(isitem(source)) diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm index 67cfeaea85c..c638196e7e9 100644 --- a/code/datums/elements/decals/blood.dm +++ b/code/datums/elements/decals/blood.dm @@ -8,7 +8,7 @@ RegisterSignal(target, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name, TRUE) -/datum/element/decal/blood/Detach(atom/source, force) +/datum/element/decal/blood/Detach(atom/source) UnregisterSignal(source, COMSIG_ATOM_GET_EXAMINE_NAME) return ..() diff --git a/code/datums/elements/drag_pickup.dm b/code/datums/elements/drag_pickup.dm index ea4fd387db5..7501d552c47 100644 --- a/code/datums/elements/drag_pickup.dm +++ b/code/datums/elements/drag_pickup.dm @@ -12,7 +12,7 @@ RegisterSignal(target, COMSIG_MOUSEDROP_ONTO, .proc/pick_up) return ..() -/datum/element/drag_pickup/Detach(datum/source, force) +/datum/element/drag_pickup/Detach(datum/source) UnregisterSignal(source, COMSIG_MOUSEDROP_ONTO) return ..() diff --git a/code/datums/elements/firestacker.dm b/code/datums/elements/firestacker.dm index de829098637..da65474dcb7 100644 --- a/code/datums/elements/firestacker.dm +++ b/code/datums/elements/firestacker.dm @@ -20,7 +20,7 @@ RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/item_attack, override = TRUE) RegisterSignal(target, COMSIG_ITEM_ATTACK_SELF, .proc/item_attack_self, override = TRUE) -/datum/element/firestacker/Detach(datum/source, force) +/datum/element/firestacker/Detach(datum/source) . = ..() UnregisterSignal(source, list(COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_SELF)) diff --git a/code/datums/elements/forced_gravity.dm b/code/datums/elements/forced_gravity.dm index b184aa989cb..ada16943b86 100644 --- a/code/datums/elements/forced_gravity.dm +++ b/code/datums/elements/forced_gravity.dm @@ -16,7 +16,7 @@ if(isturf(target)) RegisterSignal(target, COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check) -/datum/element/forced_gravity/Detach(datum/source, force) +/datum/element/forced_gravity/Detach(datum/source) . = ..() var/static/list/signals_b_gone = list(COMSIG_ATOM_HAS_GRAVITY, COMSIG_TURF_HAS_GRAVITY) UnregisterSignal(source, signals_b_gone) diff --git a/code/datums/elements/haunted.dm b/code/datums/elements/haunted.dm index 5b6ef377e2c..18a66350ffe 100644 --- a/code/datums/elements/haunted.dm +++ b/code/datums/elements/haunted.dm @@ -13,7 +13,7 @@ master.AddElement(/datum/element/movetype_handler) ADD_TRAIT(master, TRAIT_MOVE_FLYING, ELEMENT_TRAIT) -/datum/element/haunted/Detach(datum/source, force) +/datum/element/haunted/Detach(datum/source) . = ..() var/atom/movable/master = source master.remove_filter("haunt_glow") diff --git a/code/datums/elements/light_eaten.dm b/code/datums/elements/light_eaten.dm index 93678644757..8e6a70662b9 100644 --- a/code/datums/elements/light_eaten.dm +++ b/code/datums/elements/light_eaten.dm @@ -24,7 +24,7 @@ target.set_light_range(0) target.set_light_on(FALSE) -/datum/element/light_eaten/Detach(datum/source, force) +/datum/element/light_eaten/Detach(datum/source) UnregisterSignal(source, list( COMSIG_ATOM_SET_LIGHT_POWER, COMSIG_ATOM_SET_LIGHT_RANGE, diff --git a/code/datums/elements/light_eater.dm b/code/datums/elements/light_eater.dm index daf38a83ab2..236a7ce961c 100644 --- a/code/datums/elements/light_eater.dm +++ b/code/datums/elements/light_eater.dm @@ -22,7 +22,7 @@ return ..() -/datum/element/light_eater/Detach(datum/source, force) +/datum/element/light_eater/Detach(datum/source) UnregisterSignal(source, list( COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_AFTERATTACK, diff --git a/code/datums/elements/ridable.dm b/code/datums/elements/ridable.dm index 68d01da6bf8..faeb6172164 100644 --- a/code/datums/elements/ridable.dm +++ b/code/datums/elements/ridable.dm @@ -31,7 +31,7 @@ if(isvehicle(target)) RegisterSignal(target, COMSIG_PARENT_ATTACKBY, .proc/check_potion) -/datum/element/ridable/Detach(datum/target, force) +/datum/element/ridable/Detach(datum/target) UnregisterSignal(target, list(COMSIG_MOVABLE_PREBUCKLE, COMSIG_PARENT_ATTACKBY)) return ..() diff --git a/code/datums/elements/selfknockback.dm b/code/datums/elements/selfknockback.dm index c99f8ab4cc2..3c41161e941 100644 --- a/code/datums/elements/selfknockback.dm +++ b/code/datums/elements/selfknockback.dm @@ -20,7 +20,7 @@ clamping the Knockback_Force value below. */ override_throw_val = throw_amount override_speed_val = speed_amount -/datum/element/selfknockback/Detach(datum/source, force) +/datum/element/selfknockback/Detach(datum/source) . = ..() UnregisterSignal(source, list(COMSIG_ITEM_AFTERATTACK, COMSIG_PROJECTILE_FIRE)) diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index 50b1c8e2d3e..c4122b958e7 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -24,7 +24,7 @@ src.items = items src.should_strip_proc_path = should_strip_proc_path -/datum/element/strippable/Detach(datum/source, force) +/datum/element/strippable/Detach(datum/source) . = ..() UnregisterSignal(source, COMSIG_MOUSEDROP_ONTO) diff --git a/code/datums/elements/swabbable.dm b/code/datums/elements/swabbable.dm index 5059ad7635c..81ad7440eb9 100644 --- a/code/datums/elements/swabbable.dm +++ b/code/datums/elements/swabbable.dm @@ -29,7 +29,7 @@ This element is used in vat growing to allow for the object to be src.virus_chance = virus_chance ///Stops listening to the swab signal; you can no longer be swabbed. -/datum/element/swabable/Detach(datum/source, force) +/datum/element/swabable/Detach(datum/source) . = ..() if(!isatom(source) || isarea(source)) return ELEMENT_INCOMPATIBLE diff --git a/code/datums/elements/tool_flash.dm b/code/datums/elements/tool_flash.dm index cf03bdb502e..3270dbb4846 100644 --- a/code/datums/elements/tool_flash.dm +++ b/code/datums/elements/tool_flash.dm @@ -19,7 +19,7 @@ RegisterSignal(target, COMSIG_TOOL_IN_USE, .proc/prob_flash) RegisterSignal(target, COMSIG_TOOL_START_USE, .proc/flash) -/datum/element/tool_flash/Detach(datum/source, force) +/datum/element/tool_flash/Detach(datum/source) . = ..() UnregisterSignal(source, list(COMSIG_TOOL_IN_USE, COMSIG_TOOL_START_USE)) diff --git a/code/datums/elements/turf_transparency.dm b/code/datums/elements/turf_transparency.dm index fa0919d61ab..5df1b27eed5 100644 --- a/code/datums/elements/turf_transparency.dm +++ b/code/datums/elements/turf_transparency.dm @@ -22,7 +22,7 @@ update_multiz(our_turf, TRUE, TRUE) -/datum/element/turf_z_transparency/Detach(datum/source, force) +/datum/element/turf_z_transparency/Detach(datum/source) . = ..() var/turf/our_turf = source our_turf.vis_contents.len = 0 diff --git a/code/datums/elements/waddling.dm b/code/datums/elements/waddling.dm index 04a44d85f26..673b327848f 100644 --- a/code/datums/elements/waddling.dm +++ b/code/datums/elements/waddling.dm @@ -9,7 +9,7 @@ else RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/Waddle) -/datum/element/waddling/Detach(datum/source, force) +/datum/element/waddling/Detach(datum/source) . = ..() UnregisterSignal(source, COMSIG_MOVABLE_MOVED) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 296da61c3d5..53cf12d0c96 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -181,7 +181,7 @@ UnregisterSignal(user, COMSIG_MOVABLE_MOVED) UnregisterSignal(user, COMSIG_LIVING_SET_BODY_POSITION) UnregisterSignal(user, COMSIG_PARENT_QDELETING) - + /obj/machinery/door/firedoor/attack_ai(mob/user) add_fingerprint(user) if(welded || operating || machine_stat & NOPOWER) @@ -273,7 +273,7 @@ COMSIG_ATOM_EXIT = .proc/on_exit, ) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) /obj/machinery/door/firedoor/border_only/CanAllowThrough(atom/movable/mover, turf/target) . = ..() diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 56a07072780..c56b06e3a51 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -46,7 +46,7 @@ COMSIG_ATOM_EXIT = .proc/on_exit, ) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) /obj/machinery/door/window/ComponentInitialize() . = ..() diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm index fdbeb65fb73..8aa0fa9a562 100644 --- a/code/game/objects/structures/railings.dm +++ b/code/game/objects/structures/railings.dm @@ -84,7 +84,7 @@ COMSIG_ATOM_EXIT = .proc/on_exit, ) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) /obj/structure/railing/proc/on_exit(datum/source, atom/movable/leaving, atom/new_location) SIGNAL_HANDLER diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm index 27c8bbef6ad..16a9f6814e3 100644 --- a/code/game/objects/structures/stairs.dm +++ b/code/game/objects/structures/stairs.dm @@ -38,7 +38,7 @@ COMSIG_ATOM_EXIT = .proc/on_exit, ) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) return ..() diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 3501bd09c67..69a19e7d010 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -39,7 +39,7 @@ COMSIG_ATOM_EXIT = .proc/on_exit, ) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) /obj/structure/windoor_assembly/Destroy() density = FALSE diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 36a81ca0034..36efae3481c 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -73,7 +73,7 @@ ) if (flags_1 & ON_BORDER_1) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) /obj/structure/window/ComponentInitialize() . = ..() diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm index 308a88194b9..c0b4061b3e9 100644 --- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm +++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm @@ -50,7 +50,7 @@ COMSIG_ATOM_EXIT = .proc/on_exit, ) - AddElement(/datum/element/connect_loc, loc_connections) + AddElement(/datum/element/connect_loc, src, loc_connections) /obj/structure/necropolis_gate/Destroy(force) if(force) diff --git a/code/modules/unit_tests/connect_loc.dm b/code/modules/unit_tests/connect_loc.dm index b9695045597..84dc7222fc0 100644 --- a/code/modules/unit_tests/connect_loc.dm +++ b/code/modules/unit_tests/connect_loc.dm @@ -63,7 +63,7 @@ COMSIG_MOCK_SIGNAL = .proc/on_receive_mock_signal, ) - AddElement(/datum/element/connect_loc, connections) + AddElement(/datum/element/connect_loc, src, connections) /obj/item/watches_mock_calls/proc/on_receive_mock_signal(datum/source) SIGNAL_HANDLER