diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 487872df053..c0793a7a835 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -260,10 +260,6 @@ ///a deliver_first element closet was successfully delivered #define COMSIG_CLOSET_DELIVERED "crate_delivered" -///Eigenstasium -///From base of [/datum/controller/subsystem/eigenstates/proc/use_eigenlinked_atom]: (var/target) -#define COMSIG_EIGENSTATE_ACTIVATE "eigenstate_activate" - // /obj signals for economy ///called when the payment component tries to charge an account. #define COMSIG_OBJ_ATTEMPT_CHARGE "obj_attempt_simple_charge" diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm index 28d5be84c52..35084b51aca 100644 --- a/code/__DEFINES/movement.dm +++ b/code/__DEFINES/movement.dm @@ -125,8 +125,6 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) #define TELEPORT_CHANNEL_MAGIC "magic" /// Cult teleportation, does whatever it wants (unless there's holiness) #define TELEPORT_CHANNEL_CULT "cult" -/// Eigenstate teleportation, can do most things (that aren't in a teleport-prevented zone) -#define TELEPORT_CHANNEL_EIGENSTATE "eigenstate" /// Anything else #define TELEPORT_CHANNEL_FREE "free" diff --git a/code/datums/eigenstate.dm b/code/datums/eigenstate.dm index 8b113285b4b..390d79bde95 100644 --- a/code/datums/eigenstate.dm +++ b/code/datums/eigenstate.dm @@ -1,7 +1,7 @@ -GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) +GLOBAL_DATUM_INIT(closet_teleport_controller, /datum/closet_teleport_controller, new) ///A singleton used to teleport people to a linked web of itterative entries. If one entry is deleted, the 2 around it will forge a link instead. -/datum/eigenstate_manager +/datum/closet_teleport_controller ///The list of objects that something is linked to indexed by UID var/list/eigen_targets = list() ///UID to object reference @@ -10,9 +10,11 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) var/id_counter = 1 ///Limit the number of sparks created when teleporting multiple atoms to 1 var/spark_time = 0 + /// Weakref to an admin spawned eigenlinked closet - the next one spawned will link to it + var/datum/weakref/admin_link ///Creates a new link of targets unique to their own id -/datum/eigenstate_manager/proc/create_new_link(targets, subtle = TRUE) +/datum/closet_teleport_controller/proc/create_new_link(targets, subtle = TRUE) if(length(targets) <= 1) return FALSE for(var/atom/target as anything in targets) //Clear out any connected @@ -45,7 +47,6 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) RegisterSignal(target, COMSIG_QDELETING, PROC_REF(remove_eigen_entry)) if(!subtle) RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(tool_interact)) - target.RegisterSignal(target, COMSIG_EIGENSTATE_ACTIVATE, TYPE_PROC_REF(/obj/structure/closet,bust_open)) ADD_TRAIT(target, TRAIT_BANNED_FROM_CARGO_SHUTTLE, REF(src)) if(!subtle) target.add_atom_colour(COLOR_PERIWINKLEE, FIXED_COLOUR_PRIORITY) //Tint the locker slightly. @@ -57,7 +58,7 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) return TRUE ///reverts everything back to start -/datum/eigenstate_manager/eigenstates/Destroy() +/datum/closet_teleport_controller/eigenstates/Destroy() for(var/index in 1 to id_counter) for(var/entry in eigen_targets["[index]"]) remove_eigen_entry(entry) @@ -67,7 +68,7 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) return ..() ///removes an object reference from the master list -/datum/eigenstate_manager/proc/remove_eigen_entry(atom/entry) +/datum/closet_teleport_controller/proc/remove_eigen_entry(atom/entry) SIGNAL_HANDLER var/id = eigen_id[entry] eigen_targets[id] -= entry @@ -80,14 +81,13 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), )) REMOVE_TRAIT(entry, TRAIT_BANNED_FROM_CARGO_SHUTTLE, REF(src)) - entry.UnregisterSignal(entry, COMSIG_EIGENSTATE_ACTIVATE) //This is a signal on the object itself so we have to call it from that ///Remove the current entry if we're empty for(var/targets in eigen_targets) if(!length(eigen_targets[targets])) eigen_targets -= targets ///Finds the object within the master list, then sends the thing to the object's location -/datum/eigenstate_manager/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send) +/datum/closet_teleport_controller/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send) SIGNAL_HANDLER var/id = eigen_id[object_sent_from] @@ -106,8 +106,8 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) if(!eigen_target) stack_trace("No eigen target set for the eigenstate component!") return FALSE - if(check_teleport_valid(thing_to_send, eigen_target, TELEPORT_CHANNEL_EIGENSTATE)) - thing_to_send.forceMove(get_turf(eigen_target)) + if(check_teleport_valid(thing_to_send, eigen_target, TELEPORT_CHANNEL_QUANTUM)) + thing_to_send.forceMove(eigen_target) else if(!subtle) object_sent_from.balloon_alert(thing_to_send, "nothing happens!") @@ -117,12 +117,35 @@ GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) do_sparks(5, FALSE, eigen_target) do_sparks(5, FALSE, object_sent_from) spark_time = world.time - //Calls a special proc for the atom if needed (closets use bust_open()) - SEND_SIGNAL(eigen_target, COMSIG_EIGENSTATE_ACTIVATE) return COMPONENT_CLOSET_INSERT_INTERRUPT ///Prevents tool use on the item -/datum/eigenstate_manager/proc/tool_interact(atom/source, mob/user, obj/item/item) +/datum/closet_teleport_controller/proc/tool_interact(atom/source, mob/user, obj/item/item) SIGNAL_HANDLER to_chat(user, span_notice("The unstable nature of [source] makes it impossible to use [item] on [source.p_them()]!")) return ITEM_INTERACT_BLOCKING + +// For testing purposes, primarily +// Spawns a closet that will auto-link to the next one spawned +/obj/structure/closet/eigenlinked + /// Whether or not this closet subtle links (no messages/effects) + var/subtle = FALSE + +/obj/structure/closet/eigenlinked/Initialize(mapload) + . = ..() + if(mapload) + // i'm making no effort to ensure these link properly for mappers. + // add a mapping helper which uses editable ids if you want that + log_mapping("Don't map in [type], it likely won't link properly as it is intended for debug. \ + If you want this on your map you will need to add a mapping helper.") + return INITIALIZE_HINT_QDEL + + var/obj/structure/closet/other = GLOB.closet_teleport_controller.admin_link?.resolve() + if(isnull(other)) + GLOB.closet_teleport_controller.admin_link = WEAKREF(src) + return + + GLOB.closet_teleport_controller.create_new_link(list(src, other), subtle = src.subtle) + +/obj/structure/closet/eigenlinked/stealth + subtle = TRUE diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm index 1cfed1c5b49..16feace65c4 100644 --- a/code/datums/station_traits/neutral_traits.dm +++ b/code/datums/station_traits/neutral_traits.dm @@ -377,7 +377,8 @@ trait_type = STATION_TRAIT_NEUTRAL show_in_report = TRUE weight = 1 - report_message = "We've reports of high amount of trace eigenstasium on your station. Ensure that your closets are working correctly." + report_message = "We've reports of loose bluespace streams affecting your station's lockers and closets. \ + You might lose some of your belongings... or gain some new ones!" /datum/station_trait/linked_closets/on_round_start() . = ..() @@ -392,7 +393,7 @@ var/list/targets = list() for(var/how_many in 1 to rand(2,3)) targets += pick_n_take(roundstart_closets) - GLOB.eigenstate_manager.create_new_link(targets) + GLOB.closet_teleport_controller.create_new_link(targets) #define PRO_SKUB "pro-skub" diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index ff5e41f2c36..793a2afa3c3 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -176,8 +176,20 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) update_appearance() /obj/structure/closet/LateInitialize() - if(!opened && is_maploaded) - take_contents() + if(is_maploaded) + // very rare chance that a maintenance closet gets linked to another closet at roundstart + // 0.1% chance -> metastation has ~36 maintenance closets -> P(links>=1) = 3.54% per round -> about once every 30 rounds + if(prob(0.1) && istype(get_area(src), /area/station/maintenance)) + var/list/targets = GLOB.roundstart_station_closets.Copy() - src + var/list/picked = list(src) + for(var/i in 1 to pick(1, 2)) + picked += pick_n_take(targets) + GLOB.closet_teleport_controller.create_new_link(picked, subtle = TRUE) + if(!opened) + open(force = TRUE, special_effects = FALSE) + + if(!opened) + take_contents() if(sealed) var/datum/gas_mixture/external_air = loc.return_air() diff --git a/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm b/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm index 8caeb53906e..1865e75b205 100644 --- a/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm +++ b/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm @@ -107,15 +107,3 @@ do_sparks(5, FALSE, living_mob) //FOR ADDICTION-LIKE EFFECTS, SEE datum/status_effect/eigenstasium - -///Lets you link lockers together -/datum/reagent/eigenstate/expose_turf(turf/exposed_turf, reac_volume) - . = ..() - if(creation_purity < 0.8) - return - var/list/lockers = list() - for(var/obj/structure/closet/closet in exposed_turf.contents) - lockers += closet - if(!lockers.len) - return - GLOB.eigenstate_manager.create_new_link(lockers, subtle = FALSE)