Files
Aurora.3/code/modules/research/research.dm
Geeves 2cb2bce2af Gradual Research (#9342)
The RnD Console UI has been overhauled.
    RnD levels are now a gradual progress instead of just leveling up, not much has changed, but deconstructed items now give more * Data disks now tell you what they contain.
    The red scanning goggles now let you see examined items' tech levels.
    RnD consoles should now open on the main menu instead of the research menu.
    Ejected items from the RnD console and destructive analyzer now go into your hands if you're adjacent.
2020-07-18 23:36:06 +03:00

281 lines
11 KiB
Plaintext

/*
General Explination:
The research datum is the "folder" where all the research information is stored in a R&D console. It's also a holder for all the
various procs used to manipulate it. It has four variables and seven procs:
Variables:
- possible_tech is a list of all the /datum/tech that can potentially be researched by the player. The RefreshResearch() proc
(explained later) only goes through those when refreshing what you know. Generally, possible_tech contains ALL of the existing tech
but it is possible to add tech to the game that DON'T start in it (example: Xeno tech). Generally speaking, you don't want to mess
with these since they should be the default version of the datums. They're actually stored in a list rather then using typesof to
refer to them since it makes it a bit easier to search through them for specific information.
- know_tech is the companion list to possible_tech. It's the tech you can actually research and improve. Until it's added to this
list, it can't be improved. All the tech in this list are visible to the player.
- possible_designs is functionally identical to possbile_tech except it's for /datum/design.
- known_designs is functionally identical to known_tech except it's for /datum/design
Procs:
- TechHasReqs: Used by other procs (specifically RefreshResearch) to see whether all of a tech's requirements are currently in
known_tech and at a high enough level.
- DesignHasReqs: Same as TechHasReqs but for /datum/design and known_design.
- AddTech2Known: Adds a /datum/tech to known_tech. It checks to see whether it already has that tech (if so, it just replaces it). If
it doesn't have it, it adds it. Note: It does NOT check possible_tech at all. So if you want to add something strange to it (like
a player made tech?) you can.
- AddDesign2Known: Same as AddTech2Known except for /datum/design and known_designs.
- RefreshResearch: This is the workhorse of the R&D system. It updates the /datum/research holder and adds any unlocked tech paths
and designs you have reached the requirements for. It only checks through possible_tech and possible_designs, however, so it won't
accidentally add "secret" tech to it.
- UpdateTech is used as part of the actual researching process. It takes an ID and finds techs with that same ID in known_tech. When
it finds it, it checks to see whether it can improve it at all. If the known_tech's level is less then or equal to
the inputted level, it increases the known tech's level to the inputted level -1 or know tech's level +1 (whichever is higher).
The tech datums are the actual "tech trees" that you improve through researching. Each one has five variables:
- Name: Pretty obvious. This is often viewable to the players.
- Desc: Pretty obvious. Also player viewable.
- ID: This is the unique ID of the tech that is used by the various procs to find and/or maniuplate it.
- Level: This is the current level of the tech. All techs start at 1 and have a max of 15. Devices and some techs require a certain
level in specific techs before you can produce them.
- Req_tech: This is a list of the techs required to unlock this tech path. If left blank, it'll automatically be loaded into the
research holder datum.
*/
/***************************************************************
** Master Types **
** Includes all the helper procs and basic tech processing. **
***************************************************************/
/datum/research //Holder for all the existing, archived, and known tech. Individual to console.
var/list/known_tech = list() //List of locally known tech. Datum/tech go here.
var/list/possible_designs = list() //List of all designs.
var/list/protolathe_categories = list()
var/list/imprinter_categories = list()
var/list/known_designs = list() //List of available designs.
var/standard_start_level // The level non-antag techs are set at
var/antag_start_level // ditto but antag
var/load_tech = TRUE // Whether we should gather the techs
var/load_designs = TRUE // ditto but designs
/datum/research/New() //Insert techs into possible_tech here. Known_tech automatically updated.
if(load_tech)
for(var/tech_path in subtypesof(/datum/tech))
var/datum/tech/T = new tech_path(src)
known_tech[T.id] = T
if(!T.antag_tech)
if(standard_start_level)
T.level = standard_start_level
else
if(antag_start_level)
T.level = antag_start_level
if(load_designs)
for(var/design_path in subtypesof(/datum/design))
var/datum/design/D = new design_path(src)
if(D.build_type & PROTOLATHE)
protolathe_categories |= D.p_category
if(D.build_type & IMPRINTER)
imprinter_categories |= D.p_category
possible_designs[D.type] = D
RefreshResearch()
/datum/research/techonly
load_designs = FALSE
/datum/research/hightech
standard_start_level = 3
//Checks to see if design has all the required pre-reqs.
//Input: datum/design; Output: 0/1 (false/true)
/datum/research/proc/DesignHasReqs(var/datum/design/D)
if(!D.req_tech.len)
return TRUE
for(var/req in D.req_tech)
var/datum/tech/T = known_tech[req]
if(isnull(T))
return FALSE
if(T.level < D.req_tech[req])
return FALSE
return TRUE
//Adds a tech to known_tech list. Checks to make sure there aren't duplicates and updates existing tech's levels if needed.
//Input: datum/tech; Output: Null
/datum/research/proc/AddTech2Known(var/datum/tech/T)
if(isnull(T))
return
var/datum/tech/known = known_tech[T.id]
var/will_update_progress = FALSE
if(T.level > known.level)
known.level = T.level
known.next_level_threshold = T.next_level_threshold
known.next_level_progress = 0
will_update_progress = TRUE
else if (T.level == known.level && T.next_level_progress > known.next_level_progress)
will_update_progress = TRUE
if(will_update_progress)
known.next_level_progress = T.next_level_progress
/datum/research/proc/AddDesign2Known(var/datum/design/D)
known_designs[D.type] = D
//Refreshes known_tech and known_designs list
//Input/Output: n/a
/datum/research/proc/RefreshResearch()
known_designs.Cut() // this is to refresh the ordering of the designs, the alternative is an expensive insertion or sorting proc
for(var/path in possible_designs)
var/datum/design/PD = possible_designs[path]
if(DesignHasReqs(PD))
AddDesign2Known(PD)
for(var/id in known_tech)
var/datum/tech/T = known_tech[id]
T.level = between(0, T.level, MAX_TECH_LEVEL)
T.next_level_threshold = get_level_value(T.level)
/datum/research/proc/get_level_value(var/level)
return 5 ** level
//Refreshes the levels of a given tech.
//Input: Tech's ID and Level; Output: null
/datum/research/proc/UpdateTech(var/ID, var/update_level)
var/datum/tech/KT = known_tech[ID]
var/progress = get_level_value(update_level)
while(progress > 0)
if(KT.level >= MAX_TECH_LEVEL)
break
if(KT.next_level_progress + progress >= KT.next_level_threshold)
progress -= KT.next_level_threshold - KT.next_level_progress
KT.level++
KT.level = clamp(KT.level, 0, MAX_TECH_LEVEL)
KT.next_level_threshold = get_level_value(KT.level)
continue
KT.next_level_progress += progress
break
// A simple helper proc to find the name of a tech with a given ID.
/proc/CallTechName(var/ID)
for(var/T in subtypesof(/datum/tech))
var/datum/tech/check_tech = T
if(initial(check_tech.id) == ID)
return initial(check_tech.name)
/***************************************************************
** Technology Datums **
** Includes all the various technoliges and what they make. **
***************************************************************/
/datum/tech //Datum of individual technologies.
var/name = "name" //Name of the technology.
var/desc = "description" //General description of what it does and what it makes.
var/id = "id" //An easily referenced ID. Must be alphanumeric, lower-case, and no symbols.
var/antag_tech
var/level = 1 //A simple number scale of the research level. Level 0 = Secret tech.
var/next_level_progress = 0 // The research progress until the next level is reached, makes things more gradual
var/next_level_threshold = 10 // The next threshold that must be reached before it ticks to the next level
/datum/tech/materials
name = "Materials Research"
desc = "Development of new and improved materials."
id = TECH_MATERIAL
/datum/tech/engineering
name = "Engineering Research"
desc = "Development of new and improved engineering parts."
id = TECH_ENGINEERING
/datum/tech/phorontech
name = "Phoron Research"
desc = "Research into the mysterious substance colloqually known as 'phoron'."
id = TECH_PHORON
/datum/tech/powerstorage
name = "Power Manipulation Technology"
desc = "The various technologies behind the storage and generation of electicity."
id = TECH_POWER
/datum/tech/bluespace
name = "'Blue-space' Research"
desc = "Research into the sub-reality known as 'blue-space'"
id = TECH_BLUESPACE
/datum/tech/biotech
name = "Biological Technology"
desc = "Research into the deeper mysteries of life and organic substances."
id = TECH_BIO
/datum/tech/combat
name = "Combat Systems Research"
desc = "The development of offensive and defensive systems."
id = TECH_COMBAT
/datum/tech/magnets
name = "Electromagnetic Spectrum Research"
desc = "Research into the electromagnetic spectrum. No clue how they actually work, though."
id = TECH_MAGNET
/datum/tech/programming
name = "Data Theory Research"
desc = "The development of new computer and artificial intelligence and data storage systems."
id = TECH_DATA
/datum/tech/syndicate
name = "Illegal Technologies Research"
desc = "The study of technologies that violate standard government regulations."
id = TECH_ILLEGAL
antag_tech = TRUE
level = 0
/datum/tech/arcane
name = "Arcane Research"
desc = "Research into the occult and arcane field for use in practical science"
id = TECH_ARCANE
antag_tech = TRUE
level = 0
/obj/item/disk/tech_disk
name = "technology disk"
desc = "A disk for storing technology data for further research."
icon = 'icons/obj/cloning.dmi'
icon_state = "datadisk2"
item_state = "card-id"
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 30, MATERIAL_GLASS = 10)
var/datum/tech/stored
/obj/item/disk/tech_disk/Initialize(mapload)
. = ..()
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
/obj/item/disk/tech_disk/examine(mob/user, distance)
. = ..()
if(distance <= 1)
if(stored)
to_chat(user, FONT_SMALL("It is storing the following tech:"))
to_chat(user, FONT_SMALL(" - [stored.name]: Level - [stored.level] | Progress - [stored.next_level_progress]/[stored.next_level_threshold]"))
else
to_chat(user, FONT_SMALL("It doesn't have any tech stored."))
/obj/item/disk/design_disk
name = "component design disk"
desc = "A disk for storing device design data for construction in lathes."
icon = 'icons/obj/cloning.dmi'
icon_state = "datadisk2"
item_state = "card-id"
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 30, MATERIAL_GLASS = 10)
var/datum/design/blueprint
/obj/item/disk/design_disk/Initialize(mapload)
. = ..()
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
/obj/item/disk/design_disk/examine(mob/user, distance)
. = ..()
if(distance <= 1)
if(blueprint)
to_chat(user, FONT_SMALL("It is storing the following design:"))
to_chat(user, FONT_SMALL(" - [blueprint.name]"))
else
to_chat(user, FONT_SMALL("It doesn't have any blueprint stored."))