diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index f47309dd7344..8fb22c7a7adf 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -17,7 +17,8 @@ // /datum signals #define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component) #define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component) -#define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: () +#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation +#define COMSIG_PARENT_QDELETED "parent_qdeleted" //after a datum's Destroy() is called: (force, qdel_hint), at this point none of the other components chose to interrupt qdel and Destroy has been called // /atom signals #define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) @@ -81,7 +82,7 @@ #define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force) #define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force) #define COMSIG_MOVABLE_THROW "movable_throw" //from base of atom/movable/throw_at(): (datum/thrownthing, spin) - +#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z) // /obj signals #define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) @@ -96,6 +97,7 @@ #define COMSIG_ITEM_DROPPED "item_drop" #define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker) #define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) +#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) // /obj/item/clothing signals #define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 138bfbe44a86..f871ac6a445e 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -39,8 +39,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define NO_EMP_WIRES_2 (1<<1) #define HOLOGRAM_2 (1<<2) #define FROZEN_2 (1<<3) -#define STATIONLOVING_2 (1<<4) -#define INFORM_ADMINS_ON_RELOCATE_2 (1<<5) #define BANG_PROTECT_2 (1<<6) // An item worn in the ear slot with HEALS_EARS will heal your ears each diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 3cec4248d2d7..36b25bf6c633 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -99,7 +99,6 @@ #define FIRE_PRIORITY_OBJ 40 #define FIRE_PRIORITY_ACID 40 #define FIRE_PRIOTITY_BURNING 40 -#define FIRE_PRIORITY_INBOUNDS 40 #define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_PARALLAX 65 #define FIRE_PRIORITY_FLIGHTPACKS 80 diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 548cf0489b7f..168863708c2a 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -123,8 +123,6 @@ GLOBAL_LIST_INIT(bitfields, list( "NO_EMP_WIRES_2" = NO_EMP_WIRES_2, "HOLOGRAM_2" = HOLOGRAM_2, "FRONZE_2" = FROZEN_2, - "STATIONLOVING_2" = STATIONLOVING_2, - "INFORM_ADMINS_ON_RELOCATE_2" = INFORM_ADMINS_ON_RELOCATE_2, "BANG_PROTECT_2" = BANG_PROTECT_2, "HEALS_EARS_2" = HEALS_EARS_2, "OMNITONGUE_2" = OMNITONGUE_2, diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index d0e4e1f74db1..f276da972c04 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -293,11 +293,13 @@ SUBSYSTEM_DEF(garbage) if(isnull(D.gc_destroyed)) - D.SendSignal(COMSIG_PARENT_QDELETED) + if (D.SendSignal(COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted + return D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED var/start_time = world.time var/start_tick = world.tick_usage var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up. + D.SendSignal(COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy if(world.time != start_time) I.slept_destroy++ else diff --git a/code/controllers/subsystem/inbounds.dm b/code/controllers/subsystem/inbounds.dm deleted file mode 100644 index 63063c258fbc..000000000000 --- a/code/controllers/subsystem/inbounds.dm +++ /dev/null @@ -1,30 +0,0 @@ -SUBSYSTEM_DEF(inbounds) - name = "Inbounds" - priority = FIRE_PRIORITY_INBOUNDS - flags = SS_NO_INIT - runlevels = RUNLEVEL_GAME - - var/list/processing = list() - var/list/currentrun = list() - -/datum/controller/subsystem/inbounds/stat_entry() - ..("P:[processing.len]") - -/datum/controller/subsystem/inbounds/fire(resumed = 0) - if (!resumed) - src.currentrun = processing.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - - while(currentrun.len) - var/atom/movable/thing = currentrun[currentrun.len] - currentrun.len-- - if(thing) - thing.check_in_bounds(wait) - else - SSinbounds.processing -= thing - if(MC_TICK_CHECK) - return - -/datum/controller/subsystem/inbounds/Recover() - processing = SSinbounds.processing diff --git a/code/datums/components/stationloving.dm b/code/datums/components/stationloving.dm new file mode 100644 index 000000000000..a999624c3257 --- /dev/null +++ b/code/datums/components/stationloving.dm @@ -0,0 +1,83 @@ +/datum/component/stationloving + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/inform_admins = FALSE + var/disallow_soul_imbue = TRUE + +/datum/component/stationloving/Initialize(inform_admins = FALSE) + if(!ismovableatom(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(list(COMSIG_MOVABLE_Z_CHANGED), .proc/check_in_bounds) + RegisterSignal(list(COMSIG_PARENT_PREQDELETED), .proc/check_deletion) + RegisterSignal(list(COMSIG_ITEM_IMBUE_SOUL), .proc/check_soul_imbue) + src.inform_admins = inform_admins + check_in_bounds() // Just in case something is being created outside of station/centcom + +/datum/component/stationloving/InheritComponent(datum/component/stationloving/newc, original, list/arguments) + if (original) + if (istype(newc)) + inform_admins = newc.inform_admins + else if (LAZYLEN(arguments)) + inform_admins = arguments[1] + +/datum/component/stationloving/proc/relocate() + var/targetturf = find_safe_turf() + if(!targetturf) + if(GLOB.blobstart.len > 0) + targetturf = get_turf(pick(GLOB.blobstart)) + else + CRASH("Unable to find a blobstart landmark") + + var/atom/movable/AM = parent + if(ismob(AM.loc)) + var/mob/M = AM.loc + M.transferItemToLoc(AM, targetturf, TRUE) //nodrops disks when? + else if(AM.loc.SendSignal(COMSIG_CONTAINS_STORAGE)) + AM.loc.SendSignal(COMSIG_TRY_STORAGE_TAKE, src, targetturf, TRUE) + else + AM.forceMove(targetturf) + // move the disc, so ghosts remain orbiting it even if it's "destroyed" + return targetturf + +/datum/component/stationloving/proc/check_in_bounds() + if(in_bounds()) + return + else + var/turf/currentturf = get_turf(src) + to_chat(get(parent, /mob), "You can't help but feel that you just lost something back there...") + var/turf/targetturf = relocate() + log_game("[parent] has been moved out of bounds in [COORD(currentturf)]. Moving it to [COORD(targetturf)].") + if(inform_admins) + message_admins("[parent] has been moved out of bounds in [ADMIN_COORDJMP(currentturf)]. Moving it to [ADMIN_COORDJMP(targetturf)].") + +/datum/component/stationloving/proc/check_soul_imbue() + return disallow_soul_imbue + +/datum/component/stationloving/proc/in_bounds() + 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/turf/T = get_turf(parent) + if (!T) + return FALSE + if (is_station_level(T.z) || is_centcom_level(T.z)) + return TRUE + if (is_transit_level(T.z)) + var/area/A = T.loc + if (is_type_in_typecache(A, allowed_shuttles)) + return TRUE + + return FALSE + +/datum/component/stationloving/proc/check_deletion(force) // TRUE = interrupt deletion, FALSE = proceed with deletion + + var/turf/T = get_turf(parent) + + if(inform_admins && force) + message_admins("[parent] has been !!force deleted!! in [ADMIN_COORDJMP(T)].") + log_game("[parent] has been !!force deleted!! in [COORD(T)].") + + if(!force) + var/turf/targetturf = relocate() + log_game("[parent] has been destroyed in [COORD(T)]. Moving it to [COORD(targetturf)].") + if(inform_admins) + message_admins("[parent] has been destroyed in [ADMIN_COORDJMP(T)]. Moving it to [ADMIN_COORDJMP(targetturf)].") + return TRUE + return FALSE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 67f34cef741e..c64951ca7cd8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -251,24 +251,6 @@ return 1 /atom/movable/Destroy(force) - var/inform_admins = (flags_2 & INFORM_ADMINS_ON_RELOCATE_2) - var/stationloving = (flags_2 & STATIONLOVING_2) - - if(inform_admins && force) - var/turf/T = get_turf(src) - message_admins("[src] has been !!force deleted!! in [ADMIN_COORDJMP(T)].") - log_game("[src] has been !!force deleted!! in [COORD(T)].") - - if(stationloving && !force) - var/turf/currentturf = get_turf(src) - var/turf/targetturf = relocate() - log_game("[src] has been destroyed in [COORD(currentturf)]. Moving it to [COORD(targetturf)].") - if(inform_admins) - message_admins("[src] has been destroyed in [ADMIN_COORDJMP(currentturf)]. Moving it to [ADMIN_COORDJMP(targetturf)].") - return QDEL_HINT_LETMELIVE - - if(stationloving && force) - STOP_PROCESSING(SSinbounds, src) QDEL_NULL(proximity_monitor) QDEL_NULL(language_holder) @@ -365,6 +347,7 @@ loc = null /atom/movable/proc/onTransitZ(old_z,new_z) + SendSignal(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) @@ -632,88 +615,6 @@ animate(src, pixel_y = initial(pixel_y), time = 10) floating = FALSE -/* Stationloving -* -* A stationloving atom will always teleport back to the station -* if it ever leaves the station z-levels or CentCom. It will also, -* when Destroy() is called, will teleport to a random turf on the -* station. -* -* The turf is guaranteed to be "safe" for normal humans, probably. -* If the station is SUPER SMASHED UP, it might not work. -* -* Here are some important procs: -* relocate() -* moves the atom to a safe turf on the station -* -* check_in_bounds() -* regularly called and checks if `in_bounds()` returns true. If false, it -* triggers a `relocate()`. -* -* in_bounds() -* By default, checks that the atom's z is the station z or centcom. -*/ - -/atom/movable/proc/set_stationloving(state, inform_admins=FALSE) - var/currently = (flags_2 & STATIONLOVING_2) - - if(inform_admins) - flags_2 |= INFORM_ADMINS_ON_RELOCATE_2 - else - flags_2 &= ~INFORM_ADMINS_ON_RELOCATE_2 - - if(state == currently) - return - else if(!state) - STOP_PROCESSING(SSinbounds, src) - flags_2 &= ~STATIONLOVING_2 - else - START_PROCESSING(SSinbounds, src) - flags_2 |= STATIONLOVING_2 - -/atom/movable/proc/relocate() - var/targetturf = find_safe_turf() - if(!targetturf) - if(GLOB.blobstart.len > 0) - targetturf = get_turf(pick(GLOB.blobstart)) - else - throw EXCEPTION("Unable to find a blobstart landmark") - - if(ismob(loc)) - var/mob/M = loc - M.transferItemToLoc(src, targetturf, TRUE) //nodrops disks when? - else if(loc.SendSignal(COMSIG_CONTAINS_STORAGE)) - loc.SendSignal(COMSIG_TRY_STORAGE_TAKE, src, targetturf, TRUE) - else - forceMove(targetturf) - // move the disc, so ghosts remain orbiting it even if it's "destroyed" - return targetturf - -/atom/movable/proc/check_in_bounds() - if(in_bounds()) - return - else - var/turf/currentturf = get_turf(src) - to_chat(get(src, /mob), "You can't help but feel that you just lost something back there...") - var/turf/targetturf = relocate() - log_game("[src] has been moved out of bounds in [COORD(currentturf)]. Moving it to [COORD(targetturf)].") - if(flags_2 & INFORM_ADMINS_ON_RELOCATE_2) - message_admins("[src] has been moved out of bounds in [ADMIN_COORDJMP(currentturf)]. Moving it to [ADMIN_COORDJMP(targetturf)].") - -/atom/movable/proc/in_bounds() - 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/turf/T = get_turf(src) - if (!T) - return FALSE - if (is_station_level(T.z) || is_centcom_level(T.z)) - return TRUE - if (is_transit_level(T.z)) - var/area/A = T.loc - if (is_type_in_typecache(A, allowed_shuttles)) - return TRUE - - return FALSE - /* Language procs */ /atom/movable/proc/get_language_holder(shadow=TRUE) if(language_holder) diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index 7c9d89e88d69..05f56047cb82 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -8,7 +8,9 @@ GLOBAL_VAR_INIT(highlander, FALSE) send_to_playing_players("THERE CAN BE ONLY ONE") for(var/obj/item/disk/nuclear/N in GLOB.poi_list) - N.relocate() //Gets it out of bags and such + var/datum/component/stationloving/component = N.GetComponent(/datum/component/stationloving) + if (component) + component.relocate() //Gets it out of bags and such for(var/mob/living/carbon/human/H in GLOB.player_list) if(H.stat == DEAD || !(H.client)) diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index 28df23a0b0d7..0e588c438042 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -504,15 +504,12 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/Initialize() . = ..() - var/tell_the_admins - // Only tell the admins if a REAL nuke disk is relocated - if(fake) - tell_the_admins = FALSE - else + if(!fake) GLOB.poi_list |= src - tell_the_admins = TRUE - set_stationloving(TRUE, inform_admins=tell_the_admins) +/obj/item/disk/nuclear/ComponentInitialize() + . = ..() + AddComponent(/datum/component/stationloving, !fake) /obj/item/disk/nuclear/examine(mob/user) . = ..() diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index d991a3df9c84..0739a7fb843a 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -34,7 +34,7 @@ for(var/obj/item in hand_items) // I ensouled the nuke disk once. But it's probably a really // mean tactic, so probably should discourage it. - if((item.flags_1 & ABSTRACT_1) || (item.flags_1 & NODROP_1) || (item.flags_2 & STATIONLOVING_2)) + if((item.flags_1 & ABSTRACT_1) || (item.flags_1 & NODROP_1) || item.SendSignal(COMSIG_ITEM_IMBUE_SOUL, user)) continue marked_item = item to_chat(M, "You begin to focus your very being into [item]...") diff --git a/tgstation.dme b/tgstation.dme index a3612d7a359f..0e902be48091 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -206,7 +206,6 @@ #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" #include "code\controllers\subsystem\idlenpcpool.dm" -#include "code\controllers\subsystem\inbounds.dm" #include "code\controllers\subsystem\input.dm" #include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\job.dm" @@ -333,6 +332,7 @@ #include "code\datums\components\slippery.dm" #include "code\datums\components\spooky.dm" #include "code\datums\components\squeek.dm" +#include "code\datums\components\stationloving.dm" #include "code\datums\components\swarming.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\wet_floor.dm"