Replaced most instances of Nanotrasen mentions into GATO, though I've kept some that have more sense to be kept as Nanotrasen (like nanotrasen marked stuff and such)
436 lines
15 KiB
Plaintext
436 lines
15 KiB
Plaintext
|
|
//Used \n[\s]*origin_tech[\s]*=[\s]*"[\S]+" to delete all origin techs.
|
|
//Or \n[\s]*origin_tech[\s]*=[\s]list\([A-Z_\s=0-9,]*\)
|
|
//Used \n[\s]*req_tech[\s]*=[\s]*list\(["a-z\s=0-9,]*\) to delete all req_techs.
|
|
|
|
//Techweb datums are meant to store unlocked research, being able to be stored on research consoles, servers, and disks. They are NOT global.
|
|
/datum/techweb
|
|
var/list/researched_nodes = list() //Already unlocked and all designs are now available. Assoc list, id = TRUE
|
|
var/list/visible_nodes = list() //Visible nodes, doesn't mean it can be researched. Assoc list, id = TRUE
|
|
var/list/available_nodes = list() //Nodes that can immediately be researched, all reqs met. assoc list, id = TRUE
|
|
var/list/researched_designs = list() //Designs that are available for use. Assoc list, id = TRUE
|
|
var/list/custom_designs = list() //Custom inserted designs like from disks that should survive recalculation.
|
|
var/list/boosted_nodes = list() //Already boosted nodes that can't be boosted again. node id = path of boost object.
|
|
var/list/hidden_nodes = list() //Hidden nodes. id = TRUE. Used for unhiding nodes when requirements are met by removing the entry of the node.
|
|
var/list/deconstructed_items = list() //items already deconstructed for a generic point boost. path = list(point_type = points)
|
|
var/list/research_points = list() //Available research points. type = number
|
|
var/list/obj/machinery/computer/rdconsole/consoles_accessing = list()
|
|
var/id = "generic"
|
|
var/list/research_logs = list() //IC logs.
|
|
var/largest_values = list()
|
|
var/organization = "Third-Party" //Organization name, used for display.
|
|
var/list/next_income = list() //To be applied on the next passive techweb income
|
|
var/list/last_bitcoins = list() //Current per-second production, used for display only.
|
|
var/list/discovered_mutations = list() //Mutations discovered by genetics, this way they are shared and cant be destroyed by destroying a single console
|
|
var/list/tiers = list() //Assoc list, id = number, 1 is available, 2 is all reqs are 1, so on
|
|
|
|
/datum/techweb/New()
|
|
hidden_nodes = SSresearch.techweb_nodes_hidden.Copy()
|
|
for(var/i in SSresearch.techweb_nodes_starting)
|
|
var/datum/techweb_node/DN = SSresearch.techweb_node_by_id(i)
|
|
research_node(DN, TRUE, FALSE)
|
|
return ..()
|
|
|
|
/datum/techweb/admin
|
|
id = "ADMIN"
|
|
organization = "CentCom"
|
|
|
|
/datum/techweb/admin/New() //All unlocked.
|
|
. = ..()
|
|
for(var/i in SSresearch.techweb_nodes)
|
|
var/datum/techweb_node/TN = SSresearch.techweb_nodes[i]
|
|
research_node(TN, TRUE)
|
|
for(var/i in SSresearch.point_types)
|
|
research_points[i] = INFINITY
|
|
hidden_nodes = list()
|
|
|
|
/datum/techweb/syndicate
|
|
id = "SYNDICATE"
|
|
organization = "Syndicate"
|
|
|
|
/datum/techweb/syndicate/New()
|
|
var/datum/techweb_node/syndicate_basic/Node = new()
|
|
research_node(Node, TRUE)
|
|
|
|
/datum/techweb/abductor
|
|
id = "ABDUCTOR"
|
|
organization = "Aliens"
|
|
|
|
/datum/techweb/abductor/New()
|
|
var/datum/techweb_node/alientech/Node = new()
|
|
research_node(Node, TRUE)
|
|
|
|
/datum/techweb/science //Global science techweb for RND consoles.
|
|
id = "SCIENCE"
|
|
organization = "GATO"
|
|
|
|
/datum/techweb/bepis //Should contain only 1 BEPIS tech selected at random.
|
|
id = "EXPERIMENTAL"
|
|
organization = "GATO R&D"
|
|
|
|
/datum/techweb/bepis/New()
|
|
. = ..()
|
|
var/bepis_id = pick(SSresearch.techweb_nodes_experimental) //To add a new tech to the BEPIS, add the ID to this pick list.
|
|
var/datum/techweb_node/BN = (SSresearch.techweb_node_by_id(bepis_id))
|
|
hidden_nodes -= BN.id //Has to be removed from hidden nodes
|
|
research_node(BN, TRUE, FALSE, FALSE)
|
|
update_node_status(BN)
|
|
SSresearch.techweb_nodes_experimental -= bepis_id
|
|
|
|
/datum/techweb/Destroy()
|
|
researched_nodes = null
|
|
researched_designs = null
|
|
available_nodes = null
|
|
visible_nodes = null
|
|
custom_designs = null
|
|
SSresearch.techwebs -= src
|
|
return ..()
|
|
|
|
/datum/techweb/proc/recalculate_nodes(recalculate_designs = FALSE, wipe_custom_designs = FALSE)
|
|
var/list/datum/techweb_node/processing = list()
|
|
for(var/id in researched_nodes)
|
|
processing[id] = TRUE
|
|
for(var/id in visible_nodes)
|
|
processing[id] = TRUE
|
|
for(var/id in available_nodes)
|
|
processing[id] = TRUE
|
|
if(recalculate_designs)
|
|
researched_designs = custom_designs.Copy()
|
|
if(wipe_custom_designs)
|
|
custom_designs = list()
|
|
for(var/id in processing)
|
|
update_node_status(SSresearch.techweb_node_by_id(id), FALSE)
|
|
CHECK_TICK
|
|
for(var/v in consoles_accessing)
|
|
var/obj/machinery/computer/rdconsole/V = v
|
|
V.rescan_views()
|
|
V.updateUsrDialog()
|
|
|
|
/datum/techweb/proc/add_point_list(list/pointlist, income = TRUE)
|
|
if(income) // i DO NOT TRUST byond to optimize this way properly
|
|
for(var/i in pointlist)
|
|
if(SSresearch.point_types[i] && pointlist[i] > 0)
|
|
next_income[i] += pointlist[i]
|
|
else
|
|
for(var/i in pointlist)
|
|
if(SSresearch.point_types[i] && pointlist[i] > 0)
|
|
research_points[i] += pointlist[i]
|
|
|
|
/datum/techweb/proc/add_points_all(amount)
|
|
var/list/l = SSresearch.point_types.Copy()
|
|
for(var/i in l)
|
|
l[i] = amount
|
|
add_point_list(l)
|
|
|
|
/datum/techweb/proc/commit_income()
|
|
. = next_income.Copy()
|
|
add_point_list(next_income, income = FALSE)
|
|
for(var/i in next_income)
|
|
next_income[i] = 0
|
|
|
|
/datum/techweb/proc/remove_point_list(list/pointlist)
|
|
for(var/i in pointlist)
|
|
if(SSresearch.point_types[i] && pointlist[i] > 0)
|
|
research_points[i] = max(0, research_points[i] - pointlist[i])
|
|
|
|
/datum/techweb/proc/remove_points_all(amount)
|
|
var/list/l = SSresearch.point_types.Copy()
|
|
for(var/i in l)
|
|
l[i] = amount
|
|
remove_point_list(l)
|
|
|
|
/datum/techweb/proc/modify_point_list(list/pointlist)
|
|
for(var/i in pointlist)
|
|
if(SSresearch.point_types[i] && pointlist[i] != 0)
|
|
research_points[i] = max(0, research_points[i] + pointlist[i])
|
|
|
|
/datum/techweb/proc/modify_points_all(amount)
|
|
var/list/l = SSresearch.point_types.Copy()
|
|
for(var/i in l)
|
|
l[i] = amount
|
|
modify_point_list(l)
|
|
|
|
/datum/techweb/proc/copy_research_to(datum/techweb/receiver, unlock_hidden = TRUE) //Adds any missing research to theirs.
|
|
if(unlock_hidden)
|
|
for(var/i in receiver.hidden_nodes)
|
|
CHECK_TICK
|
|
if(available_nodes[i] || researched_nodes[i] || visible_nodes[i])
|
|
receiver.hidden_nodes -= i //We can see it so let them see it too.
|
|
for(var/i in researched_nodes)
|
|
CHECK_TICK
|
|
receiver.research_node_id(i, TRUE, FALSE)
|
|
for(var/i in researched_designs)
|
|
CHECK_TICK
|
|
receiver.add_design_by_id(i)
|
|
receiver.recalculate_nodes()
|
|
|
|
/datum/techweb/proc/copy()
|
|
var/datum/techweb/returned = new()
|
|
returned.researched_nodes = researched_nodes.Copy()
|
|
returned.visible_nodes = visible_nodes.Copy()
|
|
returned.available_nodes = available_nodes.Copy()
|
|
returned.researched_designs = researched_designs.Copy()
|
|
returned.hidden_nodes = hidden_nodes.Copy()
|
|
return returned
|
|
|
|
/datum/techweb/proc/get_visible_nodes() //The way this is set up is shit but whatever.
|
|
return visible_nodes - hidden_nodes
|
|
|
|
/datum/techweb/proc/get_available_nodes()
|
|
return available_nodes - hidden_nodes
|
|
|
|
/datum/techweb/proc/get_researched_nodes()
|
|
return researched_nodes - hidden_nodes
|
|
|
|
/datum/techweb/proc/add_point_type(type, amount, income = TRUE)
|
|
if(!SSresearch.point_types[type] || (amount <= 0))
|
|
return FALSE
|
|
if(income)
|
|
next_income[type] += amount
|
|
else
|
|
research_points[type] += amount
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/modify_point_type(type, amount, income = TRUE)
|
|
if(!SSresearch.point_types[type])
|
|
return FALSE
|
|
if(income && amount > 0)
|
|
next_income[type] += amount
|
|
else
|
|
research_points[type] = max(0, research_points[type] + amount)
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/remove_point_type(type, amount)
|
|
if(!SSresearch.point_types[type] || (amount <= 0))
|
|
return FALSE
|
|
research_points[type] = max(0, research_points[type] - amount)
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/add_design_by_id(id, custom = FALSE)
|
|
return add_design(SSresearch.techweb_design_by_id(id), custom)
|
|
|
|
/datum/techweb/proc/add_design(datum/design/design, custom = FALSE)
|
|
if(!istype(design))
|
|
return FALSE
|
|
researched_designs[design.id] = design
|
|
researched_designs[design.id] = TRUE
|
|
if(custom)
|
|
custom_designs[design.id] = TRUE
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/remove_design_by_id(id, custom = FALSE)
|
|
return remove_design(SSresearch.techweb_design_by_id(id), custom)
|
|
|
|
/datum/techweb/proc/remove_design(datum/design/design, custom = FALSE)
|
|
if(!istype(design))
|
|
return FALSE
|
|
if(custom_designs[design.id] && !custom)
|
|
return FALSE
|
|
custom_designs -= design.id
|
|
researched_designs -= design.id
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/get_point_total(list/pointlist)
|
|
for(var/i in pointlist)
|
|
. += pointlist[i]
|
|
|
|
/datum/techweb/proc/can_afford(list/pointlist)
|
|
for(var/i in pointlist)
|
|
if(research_points[i] < pointlist[i])
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/printout_points()
|
|
return techweb_point_display_generic(research_points)
|
|
|
|
/datum/techweb/proc/research_node_id(id, force, auto_update_points)
|
|
return research_node(SSresearch.techweb_node_by_id(id), force, auto_update_points)
|
|
|
|
/datum/techweb/proc/research_node(datum/techweb_node/node, force = FALSE, auto_adjust_cost = TRUE)
|
|
if(!istype(node))
|
|
return FALSE
|
|
update_node_status(node)
|
|
if(!force)
|
|
if(!available_nodes[node.id] || (auto_adjust_cost && (!can_afford(node.get_price(src)))))
|
|
return FALSE
|
|
if(auto_adjust_cost)
|
|
remove_point_list(node.get_price(src))
|
|
researched_nodes[node.id] = TRUE //Add to our researched list
|
|
for(var/id in node.unlock_ids)
|
|
visible_nodes[id] = TRUE
|
|
update_node_status(SSresearch.techweb_node_by_id(id))
|
|
for(var/id in node.design_ids)
|
|
add_design_by_id(id)
|
|
update_node_status(node)
|
|
if(!istype(src, /datum/techweb/admin))
|
|
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI)
|
|
if(D)
|
|
D.adjust_money(SSeconomy.techweb_bounty)
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/unresearch_node_id(id)
|
|
return unresearch_node(SSresearch.techweb_node_by_id(id))
|
|
|
|
/datum/techweb/proc/unresearch_node(datum/techweb_node/node)
|
|
if(!istype(node))
|
|
return FALSE
|
|
researched_nodes -= node.id
|
|
recalculate_nodes(TRUE) //Fully rebuild the tree.
|
|
|
|
/datum/techweb/proc/boost_with_path(datum/techweb_node/N, itempath)
|
|
if(!istype(N) || !ispath(itempath))
|
|
return FALSE
|
|
LAZYINITLIST(boosted_nodes[N.id])
|
|
for(var/i in N.boost_item_paths[itempath])
|
|
boosted_nodes[N.id][i] = max(boosted_nodes[N.id][i], N.boost_item_paths[itempath][i])
|
|
if(N.autounlock_by_boost)
|
|
hidden_nodes -= N.id
|
|
update_node_status(N)
|
|
return TRUE
|
|
|
|
/datum/techweb/proc/update_tiers(datum/techweb_node/base)
|
|
var/list/current = list(base)
|
|
while (current.len)
|
|
var/list/next = list()
|
|
for (var/node_ in current)
|
|
var/datum/techweb_node/node = node_
|
|
var/tier = 0
|
|
if (!researched_nodes[node.id]) // researched is tier 0
|
|
for (var/id in node.prereq_ids)
|
|
var/prereq_tier = tiers[id]
|
|
tier = max(tier, prereq_tier + 1)
|
|
|
|
if (tier != tiers[node.id])
|
|
tiers[node.id] = tier
|
|
for (var/id in node.unlock_ids)
|
|
next += SSresearch.techweb_node_by_id(id)
|
|
current = next
|
|
|
|
/datum/techweb/proc/update_node_status(datum/techweb_node/node, autoupdate_consoles = TRUE)
|
|
var/researched = FALSE
|
|
var/available = FALSE
|
|
var/visible = FALSE
|
|
if(researched_nodes[node.id])
|
|
researched = TRUE
|
|
var/needed = node.prereq_ids.len
|
|
for(var/id in node.prereq_ids)
|
|
if(researched_nodes[id])
|
|
visible = TRUE
|
|
needed--
|
|
if(!needed)
|
|
available = TRUE
|
|
researched_nodes -= node.id
|
|
available_nodes -= node.id
|
|
visible_nodes -= node.id
|
|
if(hidden_nodes[node.id]) //Hidden.
|
|
return
|
|
if(researched)
|
|
researched_nodes[node.id] = TRUE
|
|
for(var/id in node.design_ids)
|
|
add_design(SSresearch.techweb_design_by_id(id))
|
|
else
|
|
if(available)
|
|
available_nodes[node.id] = TRUE
|
|
else
|
|
if(visible)
|
|
visible_nodes[node.id] = TRUE
|
|
update_tiers(node)
|
|
if(autoupdate_consoles)
|
|
for(var/v in consoles_accessing)
|
|
var/obj/machinery/computer/rdconsole/V = v
|
|
V.rescan_views()
|
|
V.updateUsrDialog()
|
|
|
|
//Laggy procs to do specific checks, just in case. Don't use them if you can just use the vars that already store all this!
|
|
/datum/techweb/proc/designHasReqs(datum/design/D)
|
|
for(var/i in researched_nodes)
|
|
var/datum/techweb_node/N = SSresearch.techweb_node_by_id(i)
|
|
if(N.design_ids[D.id])
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/datum/techweb/proc/isDesignResearched(datum/design/D)
|
|
return isDesignResearchedID(D.id)
|
|
|
|
/datum/techweb/proc/isDesignResearchedID(id)
|
|
return researched_designs[id]? SSresearch.techweb_design_by_id(id) : FALSE
|
|
|
|
/datum/techweb/proc/isNodeResearched(datum/techweb_node/N)
|
|
return isNodeResearchedID(N.id)
|
|
|
|
/datum/techweb/proc/isNodeResearchedID(id)
|
|
return researched_nodes[id]? SSresearch.techweb_node_by_id(id) : FALSE
|
|
|
|
/datum/techweb/proc/isNodeVisible(datum/techweb_node/N)
|
|
return isNodeResearchedID(N.id)
|
|
|
|
/datum/techweb/proc/isNodeVisibleID(id)
|
|
return visible_nodes[id]? SSresearch.techweb_node_by_id(id) : FALSE
|
|
|
|
/datum/techweb/proc/isNodeAvailable(datum/techweb_node/N)
|
|
return isNodeAvailableID(N.id)
|
|
|
|
/datum/techweb/proc/isNodeAvailableID(id)
|
|
return available_nodes[id]? SSresearch.techweb_node_by_id(id) : FALSE
|
|
|
|
/datum/techweb/specialized
|
|
var/allowed_buildtypes = ALL
|
|
|
|
/datum/techweb/specialized/add_design(datum/design/D)
|
|
if(!(D.build_type & allowed_buildtypes))
|
|
return FALSE
|
|
return ..()
|
|
|
|
/datum/techweb/specialized/autounlocking
|
|
var/design_autounlock_buildtypes = NONE
|
|
var/design_autounlock_skip_types = NONE
|
|
var/design_autounlock_categories = list("initial") //if a design has a buildtype that matches the abovea and either has a category in this or this is null, unlock it.
|
|
var/node_autounlock_ids = list() //autounlock nodes of this type.
|
|
|
|
/datum/techweb/specialized/autounlocking/New()
|
|
..()
|
|
autounlock()
|
|
|
|
/datum/techweb/specialized/autounlocking/proc/autounlock()
|
|
for(var/id in node_autounlock_ids)
|
|
research_node_id(id, TRUE, FALSE)
|
|
for(var/id in SSresearch.techweb_designs)
|
|
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
|
if(D.build_type & (design_autounlock_buildtypes & allowed_buildtypes) && !(D.build_type & design_autounlock_skip_types))
|
|
for(var/i in D.category)
|
|
if(i in design_autounlock_categories)
|
|
add_design_by_id(D.id)
|
|
break
|
|
|
|
/datum/techweb/specialized/autounlocking/autolathe
|
|
design_autounlock_buildtypes = AUTOLATHE
|
|
allowed_buildtypes = AUTOLATHE|TOYLATHE
|
|
|
|
/datum/techweb/specialized/autounlocking/autolathe/public
|
|
design_autounlock_skip_types = NO_PUBLIC_LATHE
|
|
|
|
/datum/techweb/specialized/autounlocking/autolathe/toy
|
|
design_autounlock_buildtypes = TOYLATHE
|
|
|
|
/datum/techweb/specialized/autounlocking/autolathe/toy/public
|
|
design_autounlock_skip_types = NO_PUBLIC_LATHE
|
|
|
|
/datum/techweb/specialized/autounlocking/limbgrower
|
|
design_autounlock_buildtypes = LIMBGROWER
|
|
allowed_buildtypes = LIMBGROWER
|
|
|
|
/datum/techweb/specialized/autounlocking/biogenerator
|
|
design_autounlock_buildtypes = BIOGENERATOR
|
|
allowed_buildtypes = BIOGENERATOR
|
|
|
|
/datum/techweb/specialized/autounlocking/smelter
|
|
design_autounlock_buildtypes = SMELTER
|
|
allowed_buildtypes = SMELTER
|
|
|
|
/datum/techweb/specialized/autounlocking/exofab
|
|
allowed_buildtypes = MECHFAB
|
|
|
|
/datum/techweb/specialized/autounlocking/autobottler
|
|
design_autounlock_buildtypes = AUTOBOTTLER
|
|
allowed_buildtypes = AUTOBOTTLER
|