Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PORT] Closet Anomaly station trait #2333

Merged
merged 2 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -12,48 +12,52 @@ 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
var/already_linked = eigen_id[target]
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)
Expand All @@ -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,
Expand All @@ -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)
Expand All @@ -104,19 +109,20 @@ 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

///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 COMPONENT_BLOCK_TOOL_ATTACK
35 changes: 35 additions & 0 deletions code/datums/station_traits/neutral_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,41 @@
for(var/obj/item/item in wallet)
item.add_fingerprint(living_mob, ignoregloves = TRUE)

/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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,6 @@
var/list/lockers = list()
for(var/obj/structure/closet/closet in exposed_turf.contents)
lockers += closet
if(!length(lockers))
if(!lockers.len)
return
SSeigenstates.create_new_link(lockers)
GLOB.eigenstate_manager.create_new_link(lockers, subtle = FALSE)
2 changes: 1 addition & 1 deletion tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,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"
Expand Down Expand Up @@ -805,6 +804,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\forced_movement.dm"
Expand Down
Loading