mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
[Ready] Fermichem part 2.3 Adds a new reagent: Eigenstasium (#56918)
Co-authored-by: Rohesie <rohesie@gmail.com> Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
This commit is contained in:
112
code/controllers/subsystem/eigenstate.dm
Normal file
112
code/controllers/subsystem/eigenstate.dm
Normal file
@@ -0,0 +1,112 @@
|
||||
///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
|
||||
///The list of objects that something is linked to indexed by UID
|
||||
var/list/eigen_targets = list()
|
||||
///UID to object reference
|
||||
var/list/eigen_id = list()
|
||||
///Unique id counter
|
||||
var/id_counter = 1
|
||||
///Limit the number of sparks created when teleporting multiple atoms to 1
|
||||
var/spark_time = 0
|
||||
|
||||
///Creates a new link of targets unique to their own id
|
||||
/datum/controller/subsystem/eigenstates/proc/create_new_link(targets)
|
||||
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!")
|
||||
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
|
||||
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!")
|
||||
return FALSE
|
||||
|
||||
eigen_targets["[id_counter]"] = list() //Add to the master list
|
||||
for(var/atom/target as anything in targets)
|
||||
eigen_targets["[id_counter]"] += target
|
||||
eigen_id[target] = "[id_counter]"
|
||||
RegisterSignal(target, COMSIG_CLOSET_INSERT, .proc/use_eigenlinked_atom)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/remove_eigen_entry)
|
||||
RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), .proc/tool_interact)
|
||||
target.RegisterSignal(target, COMSIG_EIGENSTATE_ACTIVATE, /obj/structure/closet/proc/bust_open)
|
||||
var/obj/item = target
|
||||
if(item)
|
||||
item.color = COLOR_PERIWINKLEE //Tint the locker slightly.
|
||||
item.alpha = 200
|
||||
do_sparks(3, FALSE, item)
|
||||
|
||||
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()
|
||||
for(var/index in 1 to id_counter)
|
||||
for(var/entry in eigen_targets["[index]"])
|
||||
remove_eigen_entry(entry)
|
||||
eigen_targets = null
|
||||
eigen_id = null
|
||||
id_counter = 1
|
||||
return ..()
|
||||
|
||||
///removes an object reference from the master list
|
||||
/datum/controller/subsystem/eigenstates/proc/remove_eigen_entry(atom/entry)
|
||||
var/id = eigen_id[entry]
|
||||
eigen_targets[id] -= entry
|
||||
eigen_id -= entry
|
||||
entry.color = COLOR_WHITE
|
||||
entry.alpha = 255
|
||||
UnregisterSignal(entry, list(
|
||||
COMSIG_PARENT_QDELETING,
|
||||
COMSIG_CLOSET_INSERT,
|
||||
COMSIG_ATOM_TOOL_ACT(TOOL_WELDER),
|
||||
))
|
||||
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/controller/subsystem/eigenstates/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send)
|
||||
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/list/items = eigen_targets[id]
|
||||
var/index = (items.Find(object_sent_from))+1 //index + 1
|
||||
if(!index)
|
||||
stack_trace("[object_sent_from] attempted to eigenlink to something that didn't contain it!")
|
||||
return FALSE
|
||||
if(index > length(eigen_targets[id]))//If we're at the end of the list (or we're 1 length long)
|
||||
index = 1
|
||||
var/atom/eigen_target = eigen_targets[id][index]
|
||||
if(!eigen_target)
|
||||
stack_trace("No eigen target set for the eigenstate component!")
|
||||
return FALSE
|
||||
thing_to_send.forceMove(get_turf(eigen_target))
|
||||
//Create ONE set of sparks for ALL times in iteration
|
||||
if(spark_time != world.time)
|
||||
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/controller/subsystem/eigenstates/proc/tool_interact(atom/source, mob/user, obj/item/item)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of [source] makes it impossible to use [item] on [source.p_them()]!</span>")
|
||||
return COMPONENT_BLOCK_TOOL_ATTACK
|
||||
@@ -1,4 +1,6 @@
|
||||
#define EXP_ASSIGN_WAYFINDER 1200
|
||||
#define RANDOM_QUIRK_BONUS 3
|
||||
#define MINIMUM_RANDOM_QUIRKS 3
|
||||
//Used to process and handle roundstart quirks
|
||||
// - Quirk strings are used for faster checking in code
|
||||
// - Quirk datums are stored and hold different effects, as well as being a vector for applying trait string
|
||||
@@ -65,3 +67,69 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
|
||||
// Assign wayfinding pinpointer granting quirk if they're new
|
||||
if(cli.get_exp_living(TRUE) < EXP_ASSIGN_WAYFINDER && !user.has_quirk(/datum/quirk/needswayfinder))
|
||||
user.add_quirk(/datum/quirk/needswayfinder, TRUE)
|
||||
|
||||
/*
|
||||
*Randomises the quirks for a specified mob
|
||||
*/
|
||||
/datum/controller/subsystem/processing/quirks/proc/randomise_quirks(mob/living/user)
|
||||
var/bonus_quirks = max((length(user.roundstart_quirks) + rand(-RANDOM_QUIRK_BONUS, RANDOM_QUIRK_BONUS)), MINIMUM_RANDOM_QUIRKS)
|
||||
var/added_quirk_count = 0 //How many we've added
|
||||
var/list/quirks_to_add = list() //Quirks we're adding
|
||||
var/good_count = 0 //Maximum of 6 good perks
|
||||
var/score //What point score we're at
|
||||
///Cached list of possible quirks
|
||||
var/list/possible_quirks = quirks.Copy()
|
||||
//Create a random list of stuff to start with
|
||||
while(bonus_quirks > added_quirk_count)
|
||||
var/quirk = pick(possible_quirks) //quirk is a string
|
||||
if(quirk in quirk_blacklist) //prevent blacklisted
|
||||
possible_quirks -= quirk
|
||||
continue
|
||||
if(quirk_points[quirk] > 0)
|
||||
good_count++
|
||||
score += quirk_points[quirk]
|
||||
quirks_to_add += quirk
|
||||
possible_quirks -= quirk
|
||||
added_quirk_count++
|
||||
|
||||
//But lets make sure we're balanced
|
||||
while(score > 0)
|
||||
if(!length(possible_quirks))//Lets not get stuck
|
||||
break
|
||||
var/quirk = pick(quirks)
|
||||
if(quirk in quirk_blacklist) //prevent blacklisted
|
||||
possible_quirks -= quirk
|
||||
continue
|
||||
if(!quirk_points[quirk] < 0)//negative only
|
||||
possible_quirks -= quirk
|
||||
continue
|
||||
good_count++
|
||||
score += quirk_points[quirk]
|
||||
quirks_to_add += quirk
|
||||
|
||||
//And have benefits too
|
||||
while(score < 0 && good_count <= MAX_QUIRKS)
|
||||
if(!length(possible_quirks))//Lets not get stuck
|
||||
break
|
||||
var/quirk = pick(quirks)
|
||||
if(quirk in quirk_blacklist) //prevent blacklisted
|
||||
possible_quirks -= quirk
|
||||
continue
|
||||
if(!quirk_points[quirk] > 0) //positive only
|
||||
possible_quirks -= quirk
|
||||
continue
|
||||
good_count++
|
||||
score += quirk_points[quirk]
|
||||
quirks_to_add += quirk
|
||||
|
||||
for(var/datum/quirk/quirk as anything in user.roundstart_quirks)
|
||||
if(quirk.name in quirks_to_add) //Don't delete ones we keep
|
||||
quirks_to_add -= quirk.name //Already there, no need to add.
|
||||
continue
|
||||
user.remove_quirk(quirk.type) //these quirks are objects
|
||||
|
||||
for(var/datum/quirk/quirk as anything in quirks_to_add)
|
||||
user.add_quirk(quirks[quirk], spawn_effects = TRUE)//these are typepaths converted from string
|
||||
|
||||
#undef RANDOM_QUIRK_BONUS
|
||||
#undef MINIMUM_RANDOM_QUIRKS
|
||||
|
||||
Reference in New Issue
Block a user