mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-02-05 22:09:05 +00:00
Remake of #50528 About The Pull Request https://hackmd.io/@tgstation/r1tzxpwPL Basically that. Raw anomaly cores Cargo crates for them (currently 5k credits each, please tell me if this is good I balanced it relative to other crates I have no clue what the current cargo "meta"/power levels are) Finish the explosive/implosion compressor attackby and implosion procs Map in the implosion compressor Map in the roundstart 2 cores each type for science Current values are set to maxcap at the 8th core, and 4 light radius (1/2/4 explosion required) at the first core. I think this is a bit low but I'm just going off the document. The implosion compressor consumes the TTV + tanks on an attempted detonation, regardless of success. However, the "bare minimum" of checks are included (it won't let you insert incomplete TTVs. It will however, let you insert TTVs that have no explosive potential (test your bombs like you test your code ;) ), and will not waste the raw core if you fail to make a high enough radius. Props to @ArcaneMusic for the machine sprite! Why It's Good For The Game image Start of the anomaly core system I guess, gives toxins a use other than doing the quirky 50k maxcap tritium speedrun rush (or was that removed already?). Yadda yadda allows locking items behind it and another method of getting these other than supermatter overloads (I don't know if that is already gone either by the by). Changelog 🆑 add: An explosion compressor has been added to science. It makes raw anomaly cores into proper anomaly cores using prepared TTVs of a specific required blast radius. /🆑
292 lines
11 KiB
Plaintext
292 lines
11 KiB
Plaintext
|
|
SUBSYSTEM_DEF(research)
|
|
name = "Research"
|
|
priority = FIRE_PRIORITY_RESEARCH
|
|
wait = 10
|
|
init_order = INIT_ORDER_RESEARCH
|
|
//TECHWEB STATIC
|
|
var/list/techweb_nodes = list() //associative id = node datum
|
|
var/list/techweb_designs = list() //associative id = node datum
|
|
var/list/datum/techweb/techwebs = list()
|
|
var/datum/techweb/science/science_tech
|
|
var/datum/techweb/admin/admin_tech
|
|
var/datum/techweb_node/error_node/error_node //These two are what you get if a node/design is deleted and somehow still stored in a console.
|
|
var/datum/design/error_design/error_design
|
|
|
|
//ERROR LOGGING
|
|
var/list/invalid_design_ids = list() //associative id = number of times
|
|
var/list/invalid_node_ids = list() //associative id = number of times
|
|
var/list/invalid_node_boost = list() //associative id = error message
|
|
|
|
var/list/obj/machinery/rnd/server/servers = list()
|
|
|
|
var/list/techweb_nodes_starting = list() //associative id = TRUE
|
|
var/list/techweb_categories = list() //category name = list(node.id = TRUE)
|
|
var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount))
|
|
var/list/techweb_nodes_hidden = list() //Node ids that should be hidden by default.
|
|
var/list/techweb_nodes_experimental = list() //Node ids that are exclusive to the BEPIS.
|
|
var/list/techweb_point_items = list( //path = list(point type = value)
|
|
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
|
|
)
|
|
var/list/errored_datums = list()
|
|
var/list/point_types = list() //typecache style type = TRUE list
|
|
var/list/slime_already_researched = list() //Slime cores that have already been researched
|
|
//----------------------------------------------
|
|
var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = 52.3)
|
|
var/multiserver_calculation = FALSE
|
|
var/last_income
|
|
//^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
|
|
|
|
//Aiming for 1.5 hours to max R&D
|
|
//[88nodes * 5000points/node] / [1.5hr * 90min/hr * 60s/min]
|
|
//Around 450000 points max???
|
|
|
|
/// The global list of raw anomaly types that have been refined, for hard limits.
|
|
var/list/created_anomaly_types = list()
|
|
/// The hard limits of cores created for each anomaly type. For faster code lookup without switch statements.
|
|
var/list/anomaly_hard_limit_by_type = list(
|
|
ANOMALY_CORE_BLUESPACE = MAX_CORES_BLUESPACE,
|
|
ANOMALY_CORE_PYRO = MAX_CORES_PYRO,
|
|
ANOMALY_CORE_GRAVITATIONAL = MAX_CORES_GRAVITATIONAL,
|
|
ANOMALY_CORE_VORTEX = MAX_CORES_VORTEX,
|
|
ANOMALY_CORE_FLUX = MAX_CORES_FLUX
|
|
)
|
|
|
|
/datum/controller/subsystem/research/Initialize()
|
|
point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES
|
|
initialize_all_techweb_designs()
|
|
initialize_all_techweb_nodes()
|
|
science_tech = new /datum/techweb/science
|
|
admin_tech = new /datum/techweb/admin
|
|
autosort_categories()
|
|
error_design = new
|
|
error_node = new
|
|
return ..()
|
|
|
|
/datum/controller/subsystem/research/fire()
|
|
var/list/bitcoins = list()
|
|
if(multiserver_calculation)
|
|
var/eff = calculate_server_coefficient()
|
|
for(var/obj/machinery/rnd/server/miner in servers)
|
|
var/list/result = (miner.mine()) //SLAVE AWAY, SLAVE.
|
|
for(var/i in result)
|
|
result[i] *= eff
|
|
bitcoins[i] = bitcoins[i]? bitcoins[i] + result[i] : result[i]
|
|
else
|
|
for(var/obj/machinery/rnd/server/miner in servers)
|
|
if(miner.working)
|
|
bitcoins = single_server_income.Copy()
|
|
break //Just need one to work.
|
|
if (!isnull(last_income))
|
|
var/income_time_difference = world.time - last_income
|
|
science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account
|
|
for(var/i in bitcoins)
|
|
bitcoins[i] *= income_time_difference / 10
|
|
science_tech.add_point_list(bitcoins)
|
|
last_income = world.time
|
|
|
|
/datum/controller/subsystem/research/proc/calculate_server_coefficient() //Diminishing returns.
|
|
var/amt = servers.len
|
|
if(!amt)
|
|
return 0
|
|
var/coeff = 100
|
|
coeff = sqrt(coeff / amt)
|
|
return coeff
|
|
|
|
/datum/controller/subsystem/research/proc/autosort_categories()
|
|
for(var/i in techweb_nodes)
|
|
var/datum/techweb_node/I = techweb_nodes[i]
|
|
if(techweb_categories[I.category])
|
|
techweb_categories[I.category][I.id] = TRUE
|
|
else
|
|
techweb_categories[I.category] = list(I.id = TRUE)
|
|
|
|
/datum/controller/subsystem/research/proc/techweb_node_by_id(id)
|
|
return techweb_nodes[id] || error_node
|
|
|
|
/datum/controller/subsystem/research/proc/techweb_design_by_id(id)
|
|
return techweb_designs[id] || error_design
|
|
|
|
/datum/controller/subsystem/research/proc/on_design_deletion(datum/design/D)
|
|
for(var/i in techweb_nodes)
|
|
var/datum/techweb_node/TN = techwebs[i]
|
|
TN.on_design_deletion(TN)
|
|
for(var/i in techwebs)
|
|
var/datum/techweb/T = i
|
|
T.recalculate_nodes(TRUE)
|
|
|
|
/datum/controller/subsystem/research/proc/on_node_deletion(datum/techweb_node/TN)
|
|
for(var/i in techweb_nodes)
|
|
var/datum/techweb_node/TN2 = techwebs[i]
|
|
TN2.on_node_deletion(TN)
|
|
for(var/i in techwebs)
|
|
var/datum/techweb/T = i
|
|
T.recalculate_nodes(TRUE)
|
|
|
|
/datum/controller/subsystem/research/proc/initialize_all_techweb_nodes(clearall = FALSE)
|
|
if(islist(techweb_nodes) && clearall)
|
|
QDEL_LIST(techweb_nodes)
|
|
if(islist(techweb_nodes_starting && clearall))
|
|
techweb_nodes_starting.Cut()
|
|
var/list/returned = list()
|
|
for(var/path in subtypesof(/datum/techweb_node))
|
|
var/datum/techweb_node/TN = path
|
|
if(isnull(initial(TN.id)))
|
|
continue
|
|
TN = new path
|
|
if(returned[initial(TN.id)])
|
|
stack_trace("WARNING: Techweb node ID clash with ID [initial(TN.id)] detected! Path: [path]")
|
|
errored_datums[TN] = initial(TN.id)
|
|
continue
|
|
returned[initial(TN.id)] = TN
|
|
if(TN.starting_node)
|
|
techweb_nodes_starting[TN.id] = TRUE
|
|
for(var/id in techweb_nodes)
|
|
var/datum/techweb_node/TN = techweb_nodes[id]
|
|
TN.Initialize()
|
|
techweb_nodes = returned
|
|
if (!verify_techweb_nodes()) //Verify all nodes have ids and such.
|
|
stack_trace("Invalid techweb nodes detected")
|
|
calculate_techweb_nodes()
|
|
calculate_techweb_boost_list()
|
|
if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly.
|
|
CRASH("Invalid techweb nodes detected")
|
|
|
|
/datum/controller/subsystem/research/proc/initialize_all_techweb_designs(clearall = FALSE)
|
|
if(islist(techweb_designs) && clearall)
|
|
QDEL_LIST(techweb_designs)
|
|
var/list/returned = list()
|
|
for(var/path in subtypesof(/datum/design))
|
|
var/datum/design/DN = path
|
|
if(isnull(initial(DN.id)))
|
|
stack_trace("WARNING: Design with null ID detected. Build path: [initial(DN.build_path)]")
|
|
continue
|
|
else if(initial(DN.id) == DESIGN_ID_IGNORE)
|
|
continue
|
|
DN = new path
|
|
if(returned[initial(DN.id)])
|
|
stack_trace("WARNING: Design ID clash with ID [initial(DN.id)] detected! Path: [path]")
|
|
errored_datums[DN] = initial(DN.id)
|
|
continue
|
|
DN.InitializeMaterials() //Initialize the materials in the design
|
|
returned[initial(DN.id)] = DN
|
|
techweb_designs = returned
|
|
verify_techweb_designs()
|
|
|
|
|
|
/datum/controller/subsystem/research/proc/verify_techweb_nodes()
|
|
. = TRUE
|
|
for(var/n in techweb_nodes)
|
|
var/datum/techweb_node/N = techweb_nodes[n]
|
|
if(!istype(N))
|
|
WARNING("Invalid research node with ID [n] detected and removed.")
|
|
techweb_nodes -= n
|
|
research_node_id_error(n)
|
|
. = FALSE
|
|
for(var/p in N.prereq_ids)
|
|
var/datum/techweb_node/P = techweb_nodes[p]
|
|
if(!istype(P))
|
|
WARNING("Invalid research prerequisite node with ID [p] detected in node [N.display_name]\[[N.id]\] removed.")
|
|
N.prereq_ids -= p
|
|
research_node_id_error(p)
|
|
. = FALSE
|
|
for(var/d in N.design_ids)
|
|
var/datum/design/D = techweb_designs[d]
|
|
if(!istype(D))
|
|
WARNING("Invalid research design with ID [d] detected in node [N.display_name]\[[N.id]\] removed.")
|
|
N.design_ids -= d
|
|
design_id_error(d)
|
|
. = FALSE
|
|
for(var/u in N.unlock_ids)
|
|
var/datum/techweb_node/U = techweb_nodes[u]
|
|
if(!istype(U))
|
|
WARNING("Invalid research unlock node with ID [u] detected in node [N.display_name]\[[N.id]\] removed.")
|
|
N.unlock_ids -= u
|
|
research_node_id_error(u)
|
|
. = FALSE
|
|
for(var/p in N.boost_item_paths)
|
|
if(!ispath(p))
|
|
N.boost_item_paths -= p
|
|
WARNING("[p] is not a valid path.")
|
|
node_boost_error(N.id, "[p] is not a valid path.")
|
|
. = FALSE
|
|
var/list/points = N.boost_item_paths[p]
|
|
if(islist(points))
|
|
for(var/i in points)
|
|
if(!isnum(points[i]))
|
|
WARNING("[points[i]] is not a valid number.")
|
|
node_boost_error(N.id, "[points[i]] is not a valid number.")
|
|
. = FALSE
|
|
else if(!point_types[i])
|
|
WARNING("[i] is not a valid point type.")
|
|
node_boost_error(N.id, "[i] is not a valid point type.")
|
|
. = FALSE
|
|
else if(!isnull(points))
|
|
N.boost_item_paths -= p
|
|
node_boost_error(N.id, "No valid list.")
|
|
WARNING("No valid list.")
|
|
. = FALSE
|
|
CHECK_TICK
|
|
|
|
/datum/controller/subsystem/research/proc/verify_techweb_designs()
|
|
for(var/d in techweb_designs)
|
|
var/datum/design/D = techweb_designs[d]
|
|
if(!istype(D))
|
|
stack_trace("WARNING: Invalid research design with ID [d] detected and removed.")
|
|
techweb_designs -= d
|
|
CHECK_TICK
|
|
|
|
/datum/controller/subsystem/research/proc/research_node_id_error(id)
|
|
if(invalid_node_ids[id])
|
|
invalid_node_ids[id]++
|
|
else
|
|
invalid_node_ids[id] = 1
|
|
|
|
/datum/controller/subsystem/research/proc/design_id_error(id)
|
|
if(invalid_design_ids[id])
|
|
invalid_design_ids[id]++
|
|
else
|
|
invalid_design_ids[id] = 1
|
|
|
|
/datum/controller/subsystem/research/proc/calculate_techweb_nodes()
|
|
for(var/design_id in techweb_designs)
|
|
var/datum/design/D = techweb_designs[design_id]
|
|
D.unlocked_by.Cut()
|
|
for(var/node_id in techweb_nodes)
|
|
var/datum/techweb_node/node = techweb_nodes[node_id]
|
|
node.unlock_ids = list()
|
|
for(var/i in node.design_ids)
|
|
var/datum/design/D = techweb_designs[i]
|
|
node.design_ids[i] = TRUE
|
|
D.unlocked_by += node.id
|
|
if(node.hidden)
|
|
techweb_nodes_hidden[node.id] = TRUE
|
|
if(node.experimental)
|
|
techweb_nodes_experimental[node.id] = TRUE
|
|
CHECK_TICK
|
|
generate_techweb_unlock_linking()
|
|
|
|
/datum/controller/subsystem/research/proc/generate_techweb_unlock_linking()
|
|
for(var/node_id in techweb_nodes) //Clear all unlock links to avoid duplication.
|
|
var/datum/techweb_node/node = techweb_nodes[node_id]
|
|
node.unlock_ids = list()
|
|
for(var/node_id in techweb_nodes)
|
|
var/datum/techweb_node/node = techweb_nodes[node_id]
|
|
for(var/prereq_id in node.prereq_ids)
|
|
var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id)
|
|
prereq_node.unlock_ids[node.id] = node
|
|
|
|
/datum/controller/subsystem/research/proc/calculate_techweb_boost_list(clearall = FALSE)
|
|
if(clearall)
|
|
techweb_boost_items = list()
|
|
for(var/node_id in techweb_nodes)
|
|
var/datum/techweb_node/node = techweb_nodes[node_id]
|
|
for(var/path in node.boost_item_paths)
|
|
if(!ispath(path))
|
|
continue
|
|
if(length(techweb_boost_items[path]))
|
|
techweb_boost_items[path][node.id] = node.boost_item_paths[path]
|
|
else
|
|
techweb_boost_items[path] = list(node.id = node.boost_item_paths[path])
|
|
CHECK_TICK
|