diff --git a/code/controllers/subsystem/eigenstate.dm b/code/datums/eigenstate.dm similarity index 66% rename from code/controllers/subsystem/eigenstate.dm rename to code/datums/eigenstate.dm index f167fdf24d1..3bba7463209 100644 --- a/code/controllers/subsystem/eigenstate.dm +++ b/code/datums/eigenstate.dm @@ -1,7 +1,7 @@ -///Subsystem 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. -SUBSYSTEM_DEF(eigenstates) - name = "Eigenstates" - flags = SS_NO_INIT | SS_NO_FIRE +GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, 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 ///The list of objects that something is linked to indexed by UID var/list/eigen_targets = list() ///UID to object reference @@ -12,7 +12,7 @@ SUBSYSTEM_DEF(eigenstates) var/spark_time = 0 ///Creates a new link of targets unique to their own id -/datum/controller/subsystem/eigenstates/proc/create_new_link(targets) +/datum/eigenstate_manager/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 @@ -20,40 +20,44 @@ SUBSYSTEM_DEF(eigenstates) if(!already_linked) continue if(length(eigen_targets[already_linked]) > 1) //Eigenstates are notorious for having cliques! - target.visible_message("[target] fizzes, it's already linked to something else!") + if(!subtle) + target.visible_message("[target] fizzes, it's already linked to something else!") targets -= target continue - target.visible_message("[target] fizzes, collapsing it's unique wavefunction into the others!") //If we're in a eigenlink all on our own and are open to new friends + if(!subtle) + target.visible_message("[target] fizzes, collapsing it's unique wavefunction into the others!") //If we're in a eigenlink all on our own and are open to new friends remove_eigen_entry(target) //clearup for new stuff //Do we still have targets? if(!length(targets)) return FALSE var/atom/visible_atom = targets[1] //The object that'll handle the messages if(length(targets) == 1) - visible_atom.visible_message("[targets[1]] fizzes, there's nothing it can link to!") + if(!subtle) + visible_atom.visible_message("[targets[1]] fizzes, there's nothing it can link to!") return FALSE - eigen_targets["[id_counter]"] = list() //Add to the master list + var/subtle_keyword = subtle ? "subtle" : "" + eigen_targets["[id_counter][subtle_keyword]"] = list() //Add to the master list for(var/atom/target as anything in targets) - eigen_targets["[id_counter]"] += target - eigen_id[target] = "[id_counter]" + eigen_targets["[id_counter][subtle_keyword]"] += target + eigen_id[target] = "[id_counter][subtle_keyword]" RegisterSignal(target, COMSIG_CLOSET_INSERT, PROC_REF(use_eigenlinked_atom)) RegisterSignal(target, COMSIG_QDELETING, PROC_REF(remove_eigen_entry)) - RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(tool_interact)) + 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)) - var/obj/item = target - if(item) - item.color = COLOR_PERIWINKLEE //Tint the locker slightly. - item.alpha = 200 - do_sparks(3, FALSE, item) + if(!subtle) + target.add_atom_colour(COLOR_PERIWINKLEE, FIXED_COLOUR_PRIORITY) //Tint the locker slightly. + target.alpha = 200 + do_sparks(3, FALSE, target) visible_atom.visible_message("The items shimmer and fizzle, turning a shade of violet blue.") id_counter++ return TRUE ///reverts everything back to start -/datum/controller/subsystem/eigenstates/Destroy() +/datum/eigenstate_manager/eigenstates/Destroy() for(var/index in 1 to id_counter) for(var/entry in eigen_targets["[index]"]) remove_eigen_entry(entry) @@ -63,12 +67,12 @@ SUBSYSTEM_DEF(eigenstates) return ..() ///removes an object reference from the master list -/datum/controller/subsystem/eigenstates/proc/remove_eigen_entry(atom/entry) +/datum/eigenstate_manager/proc/remove_eigen_entry(atom/entry) SIGNAL_HANDLER var/id = eigen_id[entry] eigen_targets[id] -= entry eigen_id -= entry - entry.color = COLOR_WHITE + entry.remove_atom_colour(FIXED_COLOUR_PRIORITY, COLOR_PERIWINKLEE) entry.alpha = 255 UnregisterSignal(entry, list( COMSIG_QDELETING, @@ -83,13 +87,14 @@ SUBSYSTEM_DEF(eigenstates) eigen_targets -= targets ///Finds the object within the master list, then sends the thing to the object's location -/datum/controller/subsystem/eigenstates/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send) +/datum/eigenstate_manager/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send) SIGNAL_HANDLER var/id = eigen_id[object_sent_from] if(!id) stack_trace("[object_sent_from] attempted to eigenlink to something that didn't have a valid id!") return FALSE + var/subtle = findtext(id, "subtle") var/list/items = eigen_targets[id] var/index = (items.Find(object_sent_from))+1 //index + 1 if(!index) @@ -104,19 +109,21 @@ SUBSYSTEM_DEF(eigenstates) if(check_teleport_valid(thing_to_send, eigen_target, TELEPORT_CHANNEL_EIGENSTATE)) thing_to_send.forceMove(get_turf(eigen_target)) else - object_sent_from.balloon_alert(thing_to_send, "nothing happens!") + if(!subtle) + object_sent_from.balloon_alert(thing_to_send, "nothing happens!") return FALSE //Create ONE set of sparks for ALL times in iteration - if(spark_time != world.time) + if(!subtle && spark_time != world.time) do_sparks(5, FALSE, eigen_target) do_sparks(5, FALSE, object_sent_from) - spark_time = world.time + 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 + if(!subtle) + return COMPONENT_CLOSET_INSERT_INTERRUPT ///Prevents tool use on the item -/datum/controller/subsystem/eigenstates/proc/tool_interact(atom/source, mob/user, obj/item/item) +/datum/eigenstate_manager/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 diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm index f12f9bed855..905bfed2e8e 100644 --- a/code/datums/station_traits/neutral_traits.dm +++ b/code/datums/station_traits/neutral_traits.dm @@ -362,6 +362,41 @@ show_in_report = TRUE report_message = "There sure are a lot of trees out there." +/datum/station_trait/linked_closets + name = "Closet Anomaly" + 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." + +/datum/station_trait/linked_closets/on_round_start() + . = ..() + var/list/roundstart_non_secure_closets = GLOB.roundstart_station_closets.Copy() + for(var/obj/structure/closet/closet in roundstart_non_secure_closets) + if(closet.secure) + roundstart_non_secure_closets -= closet + + /** + * The number of links to perform. + * Combined with 50/50 the probability of the link being triangular, the boundaries of any given + * on-station, non-secure closet being linked are as high as 1 in 7/8 and as low as 1 in 16-17, + * nearing an a mean of 1 in 9 to 11/12 the more repetitions are done. + * + * There are more than 220 roundstart closets on meta, around 150 of which aren't secure, + * so, about 13 to 17 closets will be affected by this most of the times. + */ + var/number_of_links = round(length(roundstart_non_secure_closets) * (rand(350, 450)*0.0001), 1) + for(var/repetition in 1 to number_of_links) + var/closets_left = length(roundstart_non_secure_closets) + if(closets_left < 2) + return + var/list/targets = list() + for(var/how_many in 1 to min(closets_left, rand(2,3))) + targets += pick_n_take(roundstart_non_secure_closets) + if(closets_left == 1) //there's only one closet left. Let's not leave it alone. + targets += roundstart_non_secure_closets[1] + GLOB.eigenstate_manager.create_new_link(targets) + /datum/station_trait/triple_ai name = "AI Triumvirate" trait_type = STATION_TRAIT_NEUTRAL diff --git a/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm b/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm index 1cb0e6204c2..7c18c7e2014 100644 --- a/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm +++ b/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm @@ -118,4 +118,4 @@ lockers += closet if(!length(lockers)) return - SSeigenstates.create_new_link(lockers) + GLOB.eigenstate_manager.create_new_link(lockers) diff --git a/tgstation.dme b/tgstation.dme index 158b4532abf..5a822d8ea49 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -721,7 +721,6 @@ #include "code\controllers\subsystem\disease.dm" #include "code\controllers\subsystem\early_assets.dm" #include "code\controllers\subsystem\economy.dm" -#include "code\controllers\subsystem\eigenstate.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\explosions.dm" #include "code\controllers\subsystem\fluids.dm" @@ -859,6 +858,7 @@ #include "code\datums\dna.dm" #include "code\datums\dog_fashion.dm" #include "code\datums\ductnet.dm" +#include "code\datums\eigenstate.dm" #include "code\datums\emotes.dm" #include "code\datums\ert.dm" #include "code\datums\hailer_phrase.dm"