[MIRROR] Things that love the station may no longer leave the station, even when Dr. Anomaly says they should. (#8254)

* Things that love the station may no longer leave the station, even when Dr. Anomaly says they should. (#61335)

Bluespace anomalies detonating Move() things. When something is Move()d, none of the logic in forceMove() or doMove() is called, and thus stationloving things can't tell when they've left the z-level (since that's where the logic for it is).

There are a number of approaches I could have taken: Refactoring anomalies to use different movement code. Refactoring Movement code to send more signals in various scenarios. Refactoring the stationloving component.

I settled on two steps. First, refactoring the component to bring it up to modern code standards. Second, moving the logic for COMSIG_MOVABLE_Z_CHANGED to Moved() so the signal always fires regardless of if Move() or forceMove() or doMove() is used, with an optional var for whether the z-change is communicated to contents. This means the ore box was changed to actually send the signal instead of just returning with no parent call or signal sent. Stationloving ore boxes when?

stationloving procs no longer call SIGNAL_HANDLERs directly. Var names are now more descriptive. Things are renamed and documented. At least for the parts of the code I know.

Probably some other code cleanups.

* Things that love the station may no longer leave the station, even when Dr. Anomaly says they should.

Co-authored-by: Timberpoes <silent_insomnia_pp@hotmail.co.uk>
This commit is contained in:
SkyratBot
2021-09-18 21:45:42 +01:00
committed by GitHub
co-authored by Timberpoes
parent 84a9070213
commit 2c682cf83e
11 changed files with 114 additions and 80 deletions
+1 -1
View File
@@ -467,7 +467,7 @@
#define COMSIG_MOVABLE_POST_THROW "movable_post_throw"
///from base of datum/thrownthing/finalize(): (obj/thrown_object, datum/thrownthing) used for when a throw is finished
#define COMSIG_MOVABLE_THROW_LANDED "movable_throw_landed"
///from base of atom/movable/onTransitZ(): (old_z, new_z)
///from base of atom/movable/on_changed_z_level(): (turf/old_turf, turf/new_turf)
#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit"
///called when the movable is placed in an unaccessible area, used for stationloving: ()
#define COMSIG_MOVABLE_SECLUDED_LOCATION "movable_secluded"
+73 -49
View File
@@ -1,57 +1,67 @@
/// Teleports the movable atom back to a safe turf on the station if it leaves the z-level or becomes inaccessible.
/datum/component/stationloving
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
/// If TRUE, notifies admins when parent is teleported back to the station.
var/inform_admins = FALSE
var/disallow_soul_imbue = TRUE
var/allow_death = FALSE
/// If FALSE, prevents parent from being qdel'd unless it's a force = TRUE qdel.
var/allow_item_destruction = FALSE
/datum/component/stationloving/Initialize(inform_admins = FALSE, allow_death = FALSE)
/datum/component/stationloving/Initialize(inform_admins = FALSE, allow_item_destruction = FALSE)
if(!ismovable(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_MOVABLE_Z_CHANGED), .proc/check_in_bounds)
RegisterSignal(parent, list(COMSIG_MOVABLE_SECLUDED_LOCATION), .proc/relocate)
RegisterSignal(parent, list(COMSIG_PARENT_PREQDELETED), .proc/check_deletion)
RegisterSignal(parent, list(COMSIG_ITEM_IMBUE_SOUL), .proc/check_soul_imbue)
RegisterSignal(parent, list(COMSIG_ITEM_MARK_RETRIEVAL), .proc/check_mark_retrieval)
RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, .proc/on_parent_z_change)
RegisterSignal(parent, COMSIG_MOVABLE_SECLUDED_LOCATION, .proc/on_parent_unreachable)
RegisterSignal(parent, COMSIG_PARENT_PREQDELETED, .proc/on_parent_pre_qdeleted)
RegisterSignal(parent, COMSIG_ITEM_IMBUE_SOUL, .proc/check_soul_imbue)
RegisterSignal(parent, COMSIG_ITEM_MARK_RETRIEVAL, .proc/check_mark_retrieval)
src.inform_admins = inform_admins
src.allow_death = allow_death
check_in_bounds() // Just in case something is being created outside of station/centcom
src.allow_item_destruction = allow_item_destruction
// Just in case something is being created outside of station/centcom
if(!destination_in_bounds(parent))
relocate()
/datum/component/stationloving/InheritComponent(datum/component/stationloving/newc, original, inform_admins, allow_death)
if (original)
if (newc)
inform_admins = newc.inform_admins
allow_death = newc.allow_death
allow_death = newc.allow_item_destruction
else
inform_admins = inform_admins
/// Teleports parent to a safe turf on the station z-level.
/datum/component/stationloving/proc/relocate()
SIGNAL_HANDLER
var/target_turf = find_safe_turf()
var/targetturf = find_safe_turf()
if(!targetturf)
if(!target_turf)
if(GLOB.blobstart.len > 0)
targetturf = get_turf(pick(GLOB.blobstart))
target_turf = get_turf(pick(GLOB.blobstart))
else
CRASH("Unable to find a blobstart landmark")
var/atom/movable/AM = parent
playsound(AM, 'sound/machines/synth_no.ogg', 5, TRUE) //hey dumbass, you failed at your MOST IMPORTANT JOB, maybe you should check your chat log to see what could have caused that strange buzzing noise
AM.forceMove(targetturf)
var/atom/movable/movable_parent = parent
playsound(movable_parent, 'sound/machines/synth_no.ogg', 5, TRUE)
movable_parent.forceMove(target_turf)
to_chat(get(parent, /mob), span_danger("You can't help but feel that you just lost something back there..."))
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
return targetturf
/datum/component/stationloving/proc/check_in_bounds()
return target_turf
/// Signal handler when the parent has changed z-levels.
/// Checks to make sure it's a valid destination, if it's not then it relacates the parent instead.
/datum/component/stationloving/proc/on_parent_z_change(datum/source, turf/old_turf, turf/new_turf)
SIGNAL_HANDLER
if(in_bounds())
if(destination_in_bounds(parent))
return
else
var/turf/currentturf = get_turf(src)
var/turf/targetturf = relocate()
log_game("[parent] has been moved out of bounds in [loc_name(currentturf)]. Moving it to [loc_name(targetturf)].")
if(inform_admins)
message_admins("[parent] has been moved out of bounds in [ADMIN_VERBOSEJMP(currentturf)]. Moving it to [ADMIN_VERBOSEJMP(targetturf)].")
var/turf/current_turf = get_turf(parent)
var/turf/new_destination = relocate()
log_game("[parent] attempted to be moved out of bounds from [loc_name(old_turf)] to [loc_name(current_turf)]. Moving it to [loc_name(new_destination)].")
if(inform_admins)
message_admins("[parent] attempted to be moved out of bounds from [ADMIN_VERBOSEJMP(old_turf)] to [ADMIN_VERBOSEJMP(current_turf)]. Moving it to [ADMIN_VERBOSEJMP(new_destination)].")
return COMPONENT_MOVABLE_BLOCK_PRE_MOVE
/datum/component/stationloving/proc/check_soul_imbue()
SIGNAL_HANDLER
@@ -63,40 +73,54 @@
return COMPONENT_BLOCK_MARK_RETRIEVAL
/datum/component/stationloving/proc/in_bounds()
/// Checks whether a given destination is within bounds. Returns TRUE if it is, FALSE if it isn't.
/datum/component/stationloving/proc/destination_in_bounds(atom/destination)
var/static/list/allowed_shuttles = typecacheof(list(/area/shuttle/syndicate, /area/shuttle/escape, /area/shuttle/pod_1, /area/shuttle/pod_2, /area/shuttle/pod_3, /area/shuttle/pod_4))
var/static/list/disallowed_centcom_areas = typecacheof(list(/area/abductor_ship, /area/awaymission/errorroom))
var/turf/T = get_turf(parent)
if (!T)
var/turf/destination_turf = get_turf(destination)
if (!destination_turf)
return FALSE
var/area/A = T.loc
if (is_station_level(T.z))
var/area/destination_area = destination_turf.loc
if (is_station_level(destination_turf.z))
return TRUE
if (is_centcom_level(T.z))
if (is_type_in_typecache(A, disallowed_centcom_areas))
if (is_centcom_level(destination_turf.z))
if (is_type_in_typecache(destination_area, disallowed_centcom_areas))
return FALSE
return TRUE
if (is_reserved_level(T.z))
if (is_type_in_typecache(A, allowed_shuttles))
if (is_reserved_level(destination.z))
if (is_type_in_typecache(destination_area, allowed_shuttles))
return TRUE
return FALSE
/datum/component/stationloving/proc/check_deletion(datum/source, force) // TRUE = interrupt deletion, FALSE = proceed with deletion
/// Signal handler for before the parent is qdel'd. Can prevent the parent from being deleted where allow_item_destruction is FALSE and force is FALSE.
/datum/component/stationloving/proc/on_parent_pre_qdeleted(datum/source, force)
SIGNAL_HANDLER
var/turf/T = get_turf(parent)
var/turf/current_turf = get_turf(parent)
if(inform_admins && force)
message_admins("[parent] has been !!force deleted!! in [ADMIN_VERBOSEJMP(T)].")
log_game("[parent] has been !!force deleted!! in [loc_name(T)].")
message_admins("[parent] has been !!force deleted!! in [ADMIN_VERBOSEJMP(current_turf)].")
log_game("[parent] has been !!force deleted!! in [loc_name(current_turf)].")
if(!force && !allow_death)
var/turf/targetturf = relocate()
log_game("[parent] has been destroyed in [loc_name(T)]. Moving it to [loc_name(targetturf)].")
if(inform_admins)
message_admins("[parent] has been destroyed in [ADMIN_VERBOSEJMP(T)]. Moving it to [ADMIN_VERBOSEJMP(targetturf)].")
return TRUE
return FALSE
if(force || allow_item_destruction)
UnregisterSignal(parent, list(COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_SECLUDED_LOCATION))
return FALSE
var/turf/new_turf = relocate()
log_game("[parent] has been destroyed in [loc_name(current_turf)]. Preventing destruction and moving it to [loc_name(new_turf)].")
if(inform_admins)
message_admins("[parent] has been destroyed in [ADMIN_VERBOSEJMP(current_turf)]. Preventing destruction and moving it to [ADMIN_VERBOSEJMP(new_turf)].")
return TRUE
/// Signal handler for when the parent enters an unreachable location. Always relocates the parent.
/datum/component/stationloving/proc/on_parent_unreachable()
SIGNAL_HANDLER
var/turf/current_turf = get_turf(parent)
var/turf/new_turf = relocate()
log_game("[parent] has been moved to unreachable location in [loc_name(current_turf)]. Moving it to [loc_name(new_turf)].")
if(inform_admins)
message_admins("[parent] has been moved to unreachable location in [ADMIN_VERBOSEJMP(current_turf)]. Moving it to [ADMIN_VERBOSEJMP(new_turf)].")
return COMPONENT_MOVABLE_BLOCK_PRE_MOVE
+21 -11
View File
@@ -582,6 +582,12 @@
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, movement_dir, forced, old_locs)
var/turf/old_turf = get_turf(old_loc)
var/turf/new_turf = get_turf(src)
if (old_turf?.z != new_turf?.z)
on_changed_z_level(old_turf, new_turf)
return TRUE
@@ -733,12 +739,6 @@
oldloc.Exited(src, movement_dir)
if(old_area && old_area != destarea)
old_area.Exited(src, movement_dir)
var/turf/oldturf = get_turf(oldloc)
var/turf/destturf = get_turf(destination)
var/old_z = (oldturf ? oldturf.z : null)
var/dest_z = (destturf ? destturf.z : null)
if (old_z != dest_z)
onTransitZ(old_z, dest_z)
destination.Entered(src, oldloc)
if(destarea && old_area != destarea)
destarea.Entered(src, old_area)
@@ -757,11 +757,21 @@
Moved(oldloc, NONE, TRUE)
/atom/movable/proc/onTransitZ(old_z,new_z)
SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z)
for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care.
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
/**
* Called when a movable changes z-levels.
*
* Arguments:
* * old_z - The previous z-level they were on before.
* * notify_contents - Whether or not to notify the movable's contents that their z-level has changed.
*/
/atom/movable/proc/on_changed_z_level(turf/old_turf, turf/new_turf, notify_contents = TRUE)
SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_turf, new_turf)
if(!notify_contents)
return
for (var/atom/movable/content as anything in src) // Notify contents of Z-transition.
content.on_changed_z_level(old_turf, new_turf)
/**
* Called whenever an object moves and by mobs when they attempt to move themselves through space
+5 -5
View File
@@ -44,11 +44,11 @@
glob_lists_deregister()
return ..()
/obj/machinery/navbeacon/onTransitZ(old_z, new_z)
if (GLOB.navbeacons["[old_z]"])
GLOB.navbeacons["[old_z]"] -= src
if (GLOB.navbeacons["[new_z]"])
GLOB.navbeacons["[new_z]"] += src
/obj/machinery/navbeacon/on_changed_z_level(turf/old_turf, turf/new_turf)
if (GLOB.navbeacons["[old_turf?.z]"])
GLOB.navbeacons["[old_turf?.z]"] -= src
if (GLOB.navbeacons["[new_turf?.z]"])
GLOB.navbeacons["[new_turf?.z]"] += src
..()
// set the transponder codes assoc list from codes_txt
@@ -79,7 +79,7 @@
. = ..()
AddComponent(/datum/component/stationloving, FALSE, TRUE)
/obj/structure/blob/special/core/onTransitZ(old_z, new_z)
if(overmind && is_station_level(new_z))
/obj/structure/blob/special/core/on_changed_z_level(turf/old_turf, turf/new_turf)
if(overmind && is_station_level(new_turf?.z))
overmind.forceMove(get_turf(src))
return ..()
+1 -1
View File
@@ -37,7 +37,7 @@
/atom/movable/emissive_blocker/blob_act()
return
/atom/movable/emissive_blocker/onTransitZ()
/atom/movable/emissive_blocker/on_changed_z_level(turf/old_turf, turf/new_turf)
return
//Prevents people from moving these after creation, because they shouldn't be.
+3 -2
View File
@@ -98,5 +98,6 @@
dump_box_contents()
qdel(src)
/obj/structure/ore_box/onTransitZ()
return
/// Special override for notify_contents = FALSE.
/obj/structure/ore_box/on_changed_z_level(turf/old_turf, turf/new_turf, notify_contents = FALSE)
return ..()
+3 -3
View File
@@ -30,7 +30,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
var/turf/old_turf = get_turf(src)
var/turf/new_turf = get_turf(destination)
if (old_turf?.z != new_turf?.z)
onTransitZ(old_turf?.z, new_turf?.z)
on_changed_z_level(old_turf, new_turf)
return ..()
/mob/dead/get_status_tab_items()
@@ -119,6 +119,6 @@ INITIALIZE_IMMEDIATE(/mob/dead)
update_z(null)
return ..()
/mob/dead/onTransitZ(old_z,new_z)
/mob/dead/on_changed_z_level(turf/old_turf, turf/new_turf)
..()
update_z(new_z)
update_z(new_turf?.z)
+2 -2
View File
@@ -1596,9 +1596,9 @@
else
registered_z = null
/mob/living/onTransitZ(old_z,new_z)
/mob/living/on_changed_z_level(turf/old_turf, turf/new_turf)
..()
update_z(new_z)
update_z(new_turf?.z)
/mob/living/MouseDrop_T(atom/dropping, atom/user)
var/mob/living/U = user
@@ -662,10 +662,10 @@
if (pulledby || shouldwakeup)
toggle_ai(AI_ON)
/mob/living/simple_animal/onTransitZ(old_z, new_z)
/mob/living/simple_animal/on_changed_z_level(turf/old_turf, turf/new_turf)
..()
if (AIStatus == AI_Z_OFF)
SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src
SSidlenpcpool.idle_mobs_by_zlevel[old_turf?.z] -= src
toggle_ai(initial(AIStatus))
///This proc is used for adding the swabbale element to mobs so that they are able to be biopsied and making sure holograpic and butter-based creatures don't yield viable cells samples.
+1 -2
View File
@@ -127,10 +127,9 @@ 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)
var/turf/newT = get_turf(src)
if (newT.z != oldT.z)
onTransitZ(oldT.z, newT.z)
on_changed_z_level(oldT, newT)
if(light)
update_light()