[MIRROR] Closet Anomaly station trait. (#26883)

* Closet Anomaly station trait. (#81393)

## About The Pull Request
Well, it's a station trait that makes a small number of (non-secure)
closets function as if splashed with eigenstatium (which turns them into
teleportation cabins of some sort). However, they're subtler, they lack
the transparency and blueish tint, and don't make sparks.

This PR also demotes the Eigenstate subsystem to a singleton global
datum. It doesn't fire, it doesn't init, it plain doesn't belong amongst
the big boys.

## Why It's Good For The Game
This should be a mildly interesting station trait.

## Changelog

🆑
add: Added a 'Closet Anomaly' station trait, which links and turns a
portion of the roundstart closets into impromptu teleporters.
/🆑

* Closet Anomaly station trait.

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-03-15 13:39:23 -04:00
committed by GitHub
co-authored by Ghom
parent 5fdf13293f
commit 55cfe47aaf
4 changed files with 70 additions and 28 deletions
@@ -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
@@ -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
@@ -118,4 +118,4 @@
lockers += closet
if(!length(lockers))
return
SSeigenstates.create_new_link(lockers)
GLOB.eigenstate_manager.create_new_link(lockers)
+1 -1
View File
@@ -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"