mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 20:48:56 +01:00
[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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user