diff --git a/code/datums/components/recursive_move.dm b/code/datums/components/recursive_move.dm index 494a533a6f2..01fe4e89aaf 100644 --- a/code/datums/components/recursive_move.dm +++ b/code/datums/components/recursive_move.dm @@ -42,7 +42,10 @@ parents += cur_parent RegisterSignal(cur_parent, COMSIG_ATOM_EXITED, PROC_REF(heirarchy_changed)) RegisterSignal(cur_parent, COMSIG_QDELETING, PROC_REF(on_qdel)) - + // Because the turf is not considered to be in the heirarchy by the component, picking + // up a bag with an recursive item inside it will not rebuild the heirarchy when it + // enters the mob unless we fire this. Can't use pickup signal as it happens too early... + RegisterSignal(cur_parent, COMSIG_ITEM_EQUIPPED, PROC_REF(heirarchy_changed)) cur_parent = cur_parent.loc if(recursion >= 64) // If we escaped due to iteration limit, cancel @@ -73,6 +76,7 @@ for(var/atom/movable/cur_parent in parents) UnregisterSignal(cur_parent, COMSIG_QDELETING) UnregisterSignal(cur_parent, COMSIG_ATOM_EXITED) + UnregisterSignal(cur_parent, COMSIG_ITEM_EQUIPPED) UnregisterSignal(parents[parents.len], COMSIG_ATOM_ENTERING) diff --git a/code/datums/elements/topturfcrossed.dm b/code/datums/elements/topturfcrossed.dm new file mode 100644 index 00000000000..bbc9e546ff5 --- /dev/null +++ b/code/datums/elements/topturfcrossed.dm @@ -0,0 +1,73 @@ +/datum/component/topturfcrossed + var/atom/movable/our_owner + var/turf/our_old_turf = null + +/datum/component/topturfcrossed/Initialize() + if(!ismovable(parent)) + return COMPONENT_INCOMPATIBLE + our_owner = parent + +/datum/component/topturfcrossed/Destroy(force) + . = ..() + our_owner = null + our_old_turf = null + +/datum/component/topturfcrossed/RegisterWithParent() + our_owner.AddComponent(/datum/component/recursive_move) // Required if we want to be useful at all + RegisterSignal(our_owner, COMSIG_OBSERVER_MOVED, PROC_REF(handle_location_change)) + update_turf_signals(get_turf(our_owner)) + +/datum/component/topturfcrossed/UnregisterFromParent() + UnregisterSignal(our_owner, COMSIG_OBSERVER_MOVED) + update_turf_signals(null) + +/datum/component/topturfcrossed/proc/handle_location_change(datum/source, atom/old_loc, atom/new_loc) + SIGNAL_HANDLER + if(!our_owner) + return + update_turf_signals(new_loc) + +/// Updates the topmost turf we are registered to when we are moved. +/datum/component/topturfcrossed/proc/update_turf_signals(atom/new_loc) + // Our turf is the exact same, don't change anything! + if(new_loc && our_old_turf) + var/turf/check_valid = isturf(new_loc) ? new_loc : get_turf(new_loc) + if(check_valid == our_old_turf) + return + // Always remove the signal from our old turf when registering the new one + if(our_old_turf) + UnregisterSignal(our_old_turf, COMSIG_OBSERVER_TURF_ENTERED) + our_old_turf = null + // Only register the turf signal if we are inside something, otherwise we'd get DOUBLECROSSED + if(new_loc && !isturf(our_owner.loc)) + var/turf/find_new = isturf(new_loc) ? new_loc : get_turf(new_loc) + if(find_new) + RegisterSignal(find_new, COMSIG_OBSERVER_TURF_ENTERED, PROC_REF(handle_turf_entered)) + our_old_turf = find_new + +/// Forwards the Cross() call from the turf to the object registered +/datum/component/topturfcrossed/proc/handle_turf_entered(datum/source, datum/weakref/WF, oldloc) + SIGNAL_HANDLER + var/atom/movable/crosser = WF?.resolve() + if(QDELETED(crosser) || QDELETED(our_owner)) + return + if(isturf(our_owner.loc)) + return + if(crosser == our_owner) + return + our_owner.Crossed(crosser) + + + +//the bikehorn of testing +/obj/item/bikehorn/topturf_testing + name = "bikehorn of testing" + desc = "honk if you're working correctly" + +/obj/item/bikehorn/topturf_testing/Initialize(mapload) + . = ..() + AddComponent(/datum/component/topturfcrossed) + +/obj/item/bikehorn/topturf_testing/Crossed(atom/movable/AM) + . = ..() + to_chat(world, "[src] crossed by [AM], was inside [loc]") diff --git a/vorestation.dme b/vorestation.dme index 755aa8dcaef..cf205e1b73e 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -742,6 +742,7 @@ #include "code\datums\elements\rotatable.dm" #include "code\datums\elements\sellable.dm" #include "code\datums\elements\slosh.dm" +#include "code\datums\elements\topturfcrossed.dm" #include "code\datums\elements\turf_transparency.dm" #include "code\datums\elements\lootable\_lootable.dm" #include "code\datums\elements\lootable\boxes.dm"