"
- for(var/datum/reagent/R in linked_lathe.reagents.reagent_list)
- dat += "[R.name]: [R.volume]"
- dat += "
"
-
- ///////////////////CIRCUIT IMPRINTER SCREENS////////////////////
- if(4.0)
- dat += "
"
- dat += "
Circuit Imprinter Menu:
"
- dat += "Material Amount: [imprinter_materials.total_amount]
"
- dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
"
-
- dat += "
"
-
- dat += list_categories(linked_imprinter.categories, 4.15)
-
- if(4.15)
- dat += "
Main Menu"
- dat += "
Circuit Imprinter Menu"
- dat += "
Browsing [selected_category]:
"
- dat += "Material Amount: [imprinter_materials.total_amount]
"
- dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
"
-
- var/coeff = linked_imprinter.efficiency_coeff
- for(var/v in files.known_designs)
- var/datum/design/D = files.known_designs[v]
- if(!(selected_category in D.category) || !(D.build_type & IMPRINTER))
- continue
- var/temp_materials
- var/check_materials = 1
-
- var/all_materials = D.materials + D.reagents_list
-
- for(var/M in all_materials)
- temp_materials += " | "
- if (!linked_imprinter.check_mat(D, M))
- check_materials = 0
- temp_materials += "
[all_materials[M]/coeff] [CallMaterialName(M)]"
- else
- temp_materials += " [all_materials[M]/coeff] [CallMaterialName(M)]"
- if (check_materials)
- dat += "
[D.name][temp_materials]
"
- else
- dat += "
[D.name][temp_materials]
"
- dat += "
"
-
- if(4.17)
- dat += "
Main Menu"
- dat += "
Circuit Imprinter Menu"
- dat += "
Search results:
"
- dat += "Material Amount: [imprinter_materials.total_amount]
"
- dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
"
-
- var/coeff = linked_imprinter.efficiency_coeff
- for(var/datum/design/D in matching_designs)
- var/temp_materials
- var/check_materials = 1
- var/all_materials = D.materials + D.reagents_list
- for(var/M in all_materials)
- temp_materials += " | "
- if (!linked_imprinter.check_mat(D, M))
- check_materials = 0
- temp_materials += "
[all_materials[M]/coeff] [CallMaterialName(M)]"
- else
- temp_materials += " [all_materials[M]/coeff] [CallMaterialName(M)]"
- if (check_materials)
- dat += "
[D.name][temp_materials]
"
- else
- dat += "
[D.name][temp_materials]
"
- dat += "
"
-
- if(4.2) //Circuit Imprinter Material Storage Sub-menu
- dat += "
Main Menu"
- dat += "
Circuit Imprinter Menu"
- dat += "
Disposal All Chemicals in Storage"
- dat += "
Chemical Storage:
"
- for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list)
- dat += "[R.name]: [R.volume]"
- dat += "
Purge"
-
- if(4.3)
- dat += "
Main Menu"
- dat += "
Circuit Imprinter Menu"
- dat += "
Material Storage:
"
- if(!linked_imprinter)
- dat += "ERROR: Protolathe connection failed."
- else
- for(var/mat_id in imprinter_materials.materials)
- var/datum/material/M = imprinter_materials.materials[mat_id]
- dat += "* [M.amount] of [M.name]: "
- if(M.amount >= MINERAL_MATERIAL_AMOUNT)
- dat += "
Eject "
- if(M.amount >= MINERAL_MATERIAL_AMOUNT*5)
- dat += "
5x "
- if(M.amount >= MINERAL_MATERIAL_AMOUNT)
- dat += "
All"
- dat += "
"
- dat += "
"
-
var/datum/browser/popup = new(user, "rndconsole", name, 460, 550)
- popup.set_content(dat)
+ popup.set_content(generate_ui())
popup.open()
- return
-//helper proc, which return a table containing categories
-/obj/machinery/computer/rdconsole/proc/list_categories(list/categories, menu_num as num)
- if(!categories)
- return
+/obj/machinery/computer/rdconsole/proc/tdisk_uple_complete()
+ tdisk_uple = FALSE
+ updateUsrDialog()
- var/line_length = 1
- var/dat = "
"
+/obj/machinery/computer/rdconsole/proc/ddisk_uple_complete()
+ ddisk_uple = FALSE
+ updateUsrDialog()
- for(var/C in categories)
- if(line_length > 2)
- dat += "
"
- line_length = 1
+/obj/machinery/computer/rdconsole/proc/eject_disk(type)
+ if(type == "design")
+ d_disk.forceMove(get_turf(src))
+ d_disk = null
+ if(type == "tech")
+ t_disk.forceMove(get_turf(src))
+ t_disk = null
- dat += "| [C] | "
- line_length++
+/obj/machinery/computer/rdconsole/proc/rescan_views()
+ var/compare
+ matching_designs.Cut()
+ if(searchtype == "proto")
+ compare = PROTOLATHE
+ else if(searchtype == "imprint")
+ compare = IMPRINTER
+ for(var/v in stored_research.researched_designs)
+ var/datum/design/D = stored_research.researched_designs[v]
+ if(!(D.build_type & compare))
+ continue
+ if(findtext(D.name,searchstring))
+ matching_designs.Add(D)
- dat += "
"
- return dat
+/obj/machinery/computer/rdconsole/proc/check_canprint(datum/design/D, buildtype)
+ var/amount = 50
+ if(buildtype == IMPRINTER)
+ if(!linked_imprinter)
+ return FALSE
+ for(var/M in D.materials + D.reagents_list)
+ amount = min(amount, linked_imprinter.check_mat(D, M))
+ if(amount < 1)
+ return FALSE
+ else if(buildtype == PROTOLATHE)
+ if(!linked_lathe)
+ return FALSE
+ for(var/M in D.materials + D.reagents_list)
+ amount = min(amount, linked_lathe.check_mat(D, M))
+ if(amount < 1)
+ return FALSE
+ else
+ return FALSE
+ return amount
+
+/obj/machinery/computer/rdconsole/proc/lock_console(mob/user)
+ locked = TRUE
+
+/obj/machinery/computer/rdconsole/proc/unlock_console(mob/user)
+ locked = FALSE
/obj/machinery/computer/rdconsole/robotics
name = "Robotics R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 2
req_access = null
req_access_txt = "29"
@@ -1104,10 +935,6 @@ won't update every console in existence) but it's more of a hassle to do. Also,
/obj/machinery/computer/rdconsole/core
name = "Core R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 1
/obj/machinery/computer/rdconsole/experiment
name = "E.X.P.E.R.I-MENTOR R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 3
diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm
index b2acadb896..ad75ddf07b 100644
--- a/code/modules/research/rdmachines.dm
+++ b/code/modules/research/rdmachines.dm
@@ -3,7 +3,7 @@
//All devices that link into the R&D console fall into thise type for easy identification and some shared procs.
-/obj/machinery/r_n_d
+/obj/machinery/rnd
name = "R&D Device"
icon = 'icons/obj/machines/research.dmi'
density = TRUE
@@ -11,31 +11,34 @@
use_power = IDLE_POWER_USE
var/busy = FALSE
var/hacked = FALSE
- var/disabled = 0
+ var/disabled = FALSE
var/shocked = FALSE
var/obj/machinery/computer/rdconsole/linked_console
var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer)
-/obj/machinery/r_n_d/Initialize()
- . = ..()
- wires = new /datum/wires/r_n_d(src)
+/obj/machinery/rnd/proc/reset_busy()
+ busy = FALSE
-/obj/machinery/r_n_d/Destroy()
+/obj/machinery/rnd/Initialize()
+ . = ..()
+ wires = new /datum/wires/rnd(src)
+
+/obj/machinery/rnd/Destroy()
QDEL_NULL(wires)
return ..()
-/obj/machinery/r_n_d/proc/shock(mob/user, prb)
+/obj/machinery/rnd/proc/shock(mob/user, prb)
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
- return 0
+ return FALSE
if(!prob(prb))
- return 0
+ return FALSE
do_sparks(5, TRUE, src)
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
- return 1
+ return TRUE
else
- return 0
+ return FALSE
-/obj/machinery/r_n_d/attack_hand(mob/user)
+/obj/machinery/rnd/attack_hand(mob/user)
if(shocked)
if(shock(user,50))
return
@@ -44,10 +47,10 @@
-/obj/machinery/r_n_d/attackby(obj/item/O, mob/user, params)
+/obj/machinery/rnd/attackby(obj/item/O, mob/user, params)
if (shocked)
if(shock(user,50))
- return 1
+ return TRUE
if (default_deconstruction_screwdriver(user, "[initial(icon_state)]_t", initial(icon_state), O))
if(linked_console)
disconnect_console()
@@ -57,32 +60,28 @@
if(default_deconstruction_crowbar(O))
return
if(is_open_container() && O.is_open_container())
- return 0 //inserting reagents into the machine
+ return FALSE //inserting reagents into the machine
if(Insert_Item(O, user))
- return 1
+ return TRUE
else
return ..()
//to disconnect the machine from the r&d console it's linked to
-/obj/machinery/r_n_d/proc/disconnect_console()
+/obj/machinery/rnd/proc/disconnect_console()
linked_console = null
-//proc used to handle inserting items or reagents into r_n_d machines
-/obj/machinery/r_n_d/proc/Insert_Item(obj/item/I, mob/user)
+//proc used to handle inserting items or reagents into rnd machines
+/obj/machinery/rnd/proc/Insert_Item(obj/item/I, mob/user)
return
//whether the machine can have an item inserted in its current state.
-/obj/machinery/r_n_d/proc/is_insertion_ready(mob/user)
+/obj/machinery/rnd/proc/is_insertion_ready(mob/user)
if(panel_open)
to_chat(user, "
You can't load [src] while it's opened!")
return
if (disabled)
return
if (!linked_console) // Try to auto-connect to new RnD consoles nearby.
- for(var/obj/machinery/computer/rdconsole/console in oview(3, src))
- if(console.first_use)
- console.SyncRDevices()
-
if(!linked_console)
to_chat(user, "
[src] must be linked to an R&D console first!")
return
@@ -98,16 +97,16 @@
if(loaded_item)
to_chat(user, "
[src] is already loaded.")
return
- return 1
+ return TRUE
//we eject the loaded item when deconstructing the machine
-/obj/machinery/r_n_d/on_deconstruction()
+/obj/machinery/rnd/on_deconstruction()
if(loaded_item)
loaded_item.forceMove(loc)
..()
-/obj/machinery/r_n_d/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
+/obj/machinery/rnd/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
var/stack_name
if(ispath(type_inserted, /obj/item/ore/bluespace_crystal))
stack_name = "bluespace"
diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm
deleted file mode 100644
index 284e9d42e7..0000000000
--- a/code/modules/research/research.dm
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
-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 20. 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.
-
- //Datum/tech go here.
- var/list/possible_tech = list() //List of all tech in the game that players have access to (barring special events).
- var/list/known_tech = list() //List of locally known tech.
- var/list/possible_designs = list() //List of all designs.
- var/list/known_designs = list() //List of available designs.
-
-/datum/research/New() //Insert techs into possible_tech here. Known_tech automatically updated.
- for(var/T in subtypesof(/datum/tech))
- possible_tech += new T(src)
- for(var/D in subtypesof(/datum/design))
- possible_designs += new D(src)
- RefreshResearch()
-
-//Checks to see if tech has all the required pre-reqs.
-//Input: datum/tech; Output: 0/1 (false/true)
-/datum/research/proc/TechHasReqs(datum/tech/T)
- if(T.req_tech.len == 0)
- return TRUE
- for(var/req in T.req_tech)
- var/datum/tech/known = known_tech[req]
- if(!known || known.level < T.req_tech[req])
- return FALSE
- return TRUE
-
-//Checks to see if design has all the required pre-reqs.
-//Input: datum/design; Output: 0/1 (false/true)
-/datum/research/proc/DesignHasReqs(datum/design/D)//Heavily optimized -Sieve
- if(D.req_tech.len == 0)
- return TRUE
- for(var/req in D.req_tech)
- var/datum/tech/known = known_tech[req]
- if(!known || known.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(datum/tech/T)
- if(!T)
- return
- if(known_tech[T.id])
- var/datum/tech/known = known_tech[T.id]
- if(T.level > known.level)
- known.level = T.level
- return
- known_tech[T.id] = T.copy()
-
-/datum/research/proc/AddDesign2Known(datum/design/D)
- if(known_designs[D.id])
- return
- known_designs[D.id] = D
-
-//Refreshes known_tech and known_designs list.
-//Input/Output: n/a
-/datum/research/proc/RefreshResearch()
- for(var/datum/tech/PT in possible_tech)
- if(TechHasReqs(PT))
- AddTech2Known(PT)
-
- for(var/datum/design/PD in possible_designs)
- if(DesignHasReqs(PD))
- AddDesign2Known(PD)
-
- for(var/v in known_tech)
- var/datum/tech/T = known_tech[v]
- T.level = Clamp(T.level, 0, 20)
- return
-
-//Refreshes the levels of a given tech.
-//Input: Tech's ID and Level; Output: null
-/datum/research/proc/UpdateTech(ID, level)
- var/datum/tech/KT = known_tech[ID]
- if(KT && KT.level <= level)
- KT.level = max(KT.level + 1, level)
- SSblackbox.log_research(KT.name, level)
-
-//Checks if the origin level can raise current tech levels
-//Input: Tech's ID and Level; Output: TRUE for yes, FALSE for no
-/datum/research/proc/IsTechHigher(ID, level)
- var/datum/tech/KT = known_tech[ID]
- if(KT)
- if(KT.level <= level)
- return TRUE
- else
- return FALSE
-
-/datum/research/proc/FindDesignByID(id)
- return known_designs[id]
-
-/datum/research/proc/LowerTech(tech_id,value)
- var/datum/tech/T = known_tech[tech_id]
- T.level = max(initial(T.level),T.level - value)
- known_designs.Cut()
- RefreshResearch()
-
-
-//Autolathe files
-/datum/research/autolathe/New()
- for(var/T in (subtypesof(/datum/tech)))
- possible_tech += new T(src)
- for(var/path in subtypesof(/datum/design))
- var/datum/design/D = new path(src)
- possible_designs += D
- if((D.build_type & AUTOLATHE) && ("initial" in D.category)) //autolathe starts without hacked designs
- AddDesign2Known(D)
-
-//Limb Grower files
-/datum/research/limbgrower/New()
- for(var/T in (subtypesof(/datum/tech)))
- possible_tech += new T(src)
- for(var/path in subtypesof(/datum/design))
- var/datum/design/D = new path(src)
- possible_designs += D
- if((D.build_type & LIMBGROWER) && ("initial" in D.category))
- AddDesign2Known(D)
-
-/datum/research/autolathe/AddDesign2Known(datum/design/D)
- if(!(D.build_type & AUTOLATHE))
- return
- ..()
-
-//Biogenerator files
-/datum/research/biogenerator/New()
- for(var/T in (subtypesof(/datum/tech)))
- possible_tech += new T(src)
- for(var/path in subtypesof(/datum/design))
- var/datum/design/D = new path(src)
- possible_designs += D
- if((D.build_type & BIOGENERATOR) && ("initial" in D.category))
- AddDesign2Known(D)
-
-/datum/research/biogenerator/AddDesign2Known(datum/design/D)
- if(!(D.build_type & BIOGENERATOR))
- return
- ..()
-
-//Smelter files
-/datum/research/smelter/New()
- for(var/T in (subtypesof(/datum/tech)))
- possible_tech += new T(src)
- for(var/path in subtypesof(/datum/design))
- var/datum/design/D = new path(src)
- possible_designs += D
- if((D.build_type & SMELTER) && ("initial" in D.category))
- AddDesign2Known(D)
-
-/datum/research/smelter/AddDesign2Known(datum/design/D)
- if(!(D.build_type & SMELTER))
- return
- ..()
-
-
-/***************************************************************
-** 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/level = 1 //A simple number scale of the research level. Level 0 = Secret tech.
- var/rare = 1 //How much CentCom wants to get that tech. Used in supply shuttle tech cost calculation.
- var/list/req_tech = list() //List of ids associated values of techs required to research this tech. "id" = #
-
-
-//Trunk Technologies (don't require any other techs and you start knowning them).
-
-/datum/tech/materials
- name = "Materials Research"
- desc = "Development of new and improved materials."
- id = "materials"
-
-/datum/tech/engineering
- name = "Engineering Research"
- desc = "Development of new and improved engineering parts and tools."
- id = "engineering"
-
-/datum/tech/plasmatech
- name = "Plasma Research"
- desc = "Research into the mysterious substance colloquially known as \"plasma\"."
- id = "plasmatech"
- rare = 3
-
-/datum/tech/powerstorage
- name = "Power Manipulation Technology"
- desc = "The various technologies behind the storage and generation of electricity."
- id = "powerstorage"
-
-/datum/tech/bluespace
- name = "\"Blue-space\" Research"
- desc = "Research into the sub-reality known as \"blue-space\"."
- id = "bluespace"
- rare = 2
-
-/datum/tech/biotech
- name = "Biological Technology"
- desc = "Research into the deeper mysteries of life and organic substances."
- id = "biotech"
-
-/datum/tech/combat
- name = "Combat Systems Research"
- desc = "The development of offensive and defensive systems."
- id = "combat"
-
-/datum/tech/magnets
- name = "Electromagnetic Spectrum Research"
- desc = "Research into the electromagnetic spectrum. No clue how they actually work, though."
- id = "magnets"
-
-/datum/tech/programming
- name = "Data Theory Research"
- desc = "The development of new computer and artificial intelligence and data storage systems."
- id = "programming"
-
-/datum/tech/syndicate
- name = "Illegal Technologies Research"
- desc = "The study of technologies that violate Nanotrasen regulations."
- id = "syndicate"
- rare = 4
-
-
-//Secret Technologies (hidden by default, require rare items to reveal)
-
-/datum/tech/abductor
- name = "Alien Technologies Research"
- desc = "The study of technologies used by the advanced alien race known as Abductors."
- id = "abductor"
- rare = 5
- level = 0
-
-/datum/tech/arcane
- name = "Arcane Research"
- desc = "When sufficiently analyzed, any magic becomes indistinguishable from technology."
- id = "arcane"
- rare = 5
- level = 0
-
-/*
-//Branch Techs
-/datum/tech/explosives
- name = "Explosives Research"
- desc = "The creation and application of explosive materials."
- id = "explosives"
- req_tech = list("materials" = 3)
-
-/datum/tech/generators
- name = "Power Generation Technology"
- desc = "Research into more powerful and more reliable sources."
- id = "generators"
- req_tech = list("powerstorage" = 2)
-
-/datum/tech/robotics
- name = "Robotics Technology"
- desc = "The development of advanced automated, autonomous machines."
- id = "robotics"
- req_tech = list("materials" = 3, "programming" = 3)
-*/
-
-
-/datum/tech/proc/getCost(var/current_level = null)
- // Calculates tech disk's supply points sell cost
- if(!current_level)
- current_level = initial(level)
-
- if(current_level >= level)
- return 0
-
- var/cost = 0
- for(var/i=current_level+1, i<=level, i++)
- if(i == initial(level))
- continue
- cost += i*rare
-
- return cost
-
-/datum/tech/proc/copy()
- var/datum/tech/T = new type()
- T.level = level
- return T
-
-/obj/item/disk/tech_disk
- name = "technology disk"
- desc = "A disk for storing technology data for further research."
- icon_state = "datadisk0"
- materials = list(MAT_METAL=300, MAT_GLASS=100)
- var/list/tech_stored = list()
- var/max_tech_stored = 1
-
-/obj/item/disk/tech_disk/Initialize()
- . = ..()
- pixel_x = rand(-5, 5)
- pixel_y = rand(-5, 5)
- for(var/i in 1 to max_tech_stored)
- tech_stored += null
-
-
-/obj/item/disk/tech_disk/adv
- name = "advanced technology disk"
- desc = "A disk for storing technology data for further research. This one has extra storage space."
- materials = list(MAT_METAL=300, MAT_GLASS=100, MAT_SILVER=50)
- max_tech_stored = 5
-
-/obj/item/disk/tech_disk/super_adv
- name = "quantum technology disk"
- desc = "A disk for storing technology data for further research. This one has extremely large storage space."
- materials = list(MAT_METAL=300, MAT_GLASS=100, MAT_SILVER=100, MAT_GOLD=100)
- max_tech_stored = 10
-
-/obj/item/disk/tech_disk/debug
- name = "\improper CentCom technology disk"
- desc = "A debug item for research."
- materials = list()
- max_tech_stored = 0
-
-/obj/item/disk/tech_disk/debug/Initialize()
- . = ..()
- var/list/techs = subtypesof(/datum/tech)
- max_tech_stored = techs.len
- for(var/V in techs)
- var/datum/tech/T = new V()
- tech_stored += T
- T.level = 8
diff --git a/code/modules/research/research_disk.dm b/code/modules/research/research_disk.dm
new file mode 100644
index 0000000000..ac06bbdbd5
--- /dev/null
+++ b/code/modules/research/research_disk.dm
@@ -0,0 +1,22 @@
+
+/obj/item/disk/tech_disk
+ name = "technology disk"
+ desc = "A disk for storing technology data for further research."
+ icon_state = "datadisk0"
+ materials = list(MAT_METAL=300, MAT_GLASS=100)
+ var/datum/techweb/stored_research
+
+/obj/item/disk/tech_disk/Initialize()
+ . = ..()
+ pixel_x = rand(-5, 5)
+ pixel_y = rand(-5, 5)
+ stored_research = new /datum/techweb
+
+/obj/item/disk/tech_disk/debug
+ name = "centcomm technology disk"
+ desc = "A debug item for research"
+ materials = list()
+
+/obj/item/disk/tech_disk/debug/Initialize()
+ . = ..()
+ stored_research = new /datum/techweb/admin
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 9a59e63e18..8a244bcea1 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -1,99 +1,65 @@
-/obj/machinery/r_n_d/server
+/obj/machinery/rnd/server
name = "\improper R&D Server"
desc = "A computer system running a deep neural network that processes arbitrary information to produce data useable in the development of new technologies. In layman's terms, it makes research points."
icon = 'icons/obj/machines/research.dmi'
icon_state = "server"
- var/datum/research/files
+ var/datum/techweb/stored_research
var/heat_health = 100
- var/list/id_with_upload = list() //List of R&D consoles with upload to server access.
- var/list/id_with_download = list() //List of R&D consoles with download from server access.
- var/id_with_upload_string = "" //String versions for easy editing in map editor.
- var/id_with_download_string = ""
+ //Code for point mining here.
+ var/working = TRUE //temperature should break it.
var/server_id = 0
+ var/base_mining_income = 2
var/heat_gen = 100
var/heating_power = 40000
- var/delay = 10
+ var/delay = 5
+ var/temp_tolerance_low = 0
+ var/temp_tolerance_high = T20C
+ var/temp_penalty_coefficient = 0.5 //1 = -1 points per degree above high tolerance. 0.5 = -0.5 points per degree above high tolerance.
req_access = list(ACCESS_RD) //ONLY THE R&D CAN CHANGE SERVER SETTINGS.
-/obj/machinery/r_n_d/server/Initialize()
+/obj/machinery/rnd/server/Initialize()
. = ..()
+ SSresearch.servers |= src
+ stored_research = SSresearch.science_tech
var/obj/item/circuitboard/machine/B = new /obj/item/circuitboard/machine/rdserver(null)
B.apply_default_parts(src)
-/obj/machinery/r_n_d/server/Destroy()
- griefProtection()
+/obj/machinery/rnd/server/Destroy()
+ SSresearch.servers -= src
return ..()
-/obj/machinery/r_n_d/server/RefreshParts()
+/obj/machinery/rnd/server/RefreshParts()
var/tot_rating = 0
for(var/obj/item/stock_parts/SP in src)
tot_rating += SP.rating
heat_gen /= max(1, tot_rating)
-/obj/machinery/r_n_d/server/Initialize(mapload)
- . = ..()
- if(!files)
- files = new /datum/research(src)
- var/list/temp_list
- if(!id_with_upload.len)
- temp_list = list()
- temp_list = splittext(id_with_upload_string, ";")
- for(var/N in temp_list)
- id_with_upload += text2num(N)
- if(!id_with_download.len)
- temp_list = list()
- temp_list = splittext(id_with_download_string, ";")
- for(var/N in temp_list)
- id_with_download += text2num(N)
-
-/obj/machinery/r_n_d/server/process()
- var/datum/gas_mixture/environment = loc.return_air()
- switch(environment.temperature)
- if(0 to T0C)
- heat_health = min(100, heat_health + 1)
- if(T0C to (T20C + 20))
- heat_health = Clamp(heat_health, 0, 100)
- if((T20C + 20) to (T0C + 70))
- heat_health = max(0, heat_health - 1)
- if(heat_health <= 0)
- /*griefProtection() This seems to get called twice before running any code that deletes/damages the server or it's files anwyay.
- refreshParts and the hasReq procs that get called by this are laggy and do not need to be called by every server on the map every tick */
- var/updateRD = 0
- files.known_designs = list()
- for(var/v in files.known_tech)
- var/datum/tech/T = files.known_tech[v]
- if(prob(1))
- updateRD++
- T.level--
- if(updateRD)
- files.RefreshResearch()
- if(delay)
- delay--
+/obj/machinery/rnd/server/proc/refresh_working()
+ if(stat & EMPED)
+ working = FALSE
else
- produce_heat(heat_gen)
- delay = initial(delay)
+ working = TRUE
+/obj/machinery/rnd/server/emp_act()
+ stat |= EMPED
+ addtimer(CALLBACK(src, .proc/unemp), 600)
+ refresh_working()
+ return ..()
-/obj/machinery/r_n_d/server/emp_act(severity)
- griefProtection()
- ..()
+/obj/machinery/rnd/server/proc/unemp()
+ stat &= ~EMPED
+ refresh_working()
-/obj/machinery/r_n_d/server/ex_act(severity, target)
- griefProtection()
- ..()
+/obj/machinery/rnd/server/proc/mine()
+ . = base_mining_income
+ var/penalty = max((get_env_temp() - temp_tolerance_low), 0) / temp_penalty_coefficient
+ . = max(. - penalty, 0)
-//Backup files to centcom to help admins recover data after greifer attacks
-/obj/machinery/r_n_d/server/proc/griefProtection()
- for(var/obj/machinery/r_n_d/server/centcom/C in GLOB.machines)
- for(var/v in files.known_tech)
- var/datum/tech/T = files.known_tech[v]
- C.files.AddTech2Known(T)
- for(var/v in files.known_designs)
- var/datum/design/D = files.known_designs[v]
- C.files.AddDesign2Known(D)
- C.files.RefreshResearch()
+/obj/machinery/rnd/server/proc/get_env_temp()
+ var/datum/gas_mixture/environment = loc.return_air()
+ return environment.temperature
-/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt)
+/obj/machinery/rnd/server/proc/produce_heat(heat_amt)
if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater.
var/turf/L = loc
if(istype(L))
@@ -114,30 +80,17 @@
env.merge(removed)
air_update_turf()
-//called when the server is deconstructed.
-/obj/machinery/r_n_d/server/on_deconstruction()
- griefProtection()
- ..()
-
-/obj/machinery/r_n_d/server/attack_hand(mob/user as mob) // I guess only exists to stop ninjas or hell does it even work I dunno. See also ninja gloves.
+/obj/machinery/rnd/server/attack_hand(mob/user as mob) // I guess only exists to stop ninjas or hell does it even work I dunno. See also ninja gloves.
if (disabled)
return
if (shocked)
shock(user,50)
return
-/obj/machinery/r_n_d/server/centcom
- name = "CentCom Central R&D Database"
- server_id = -1
-
-/obj/machinery/r_n_d/server/centcom/Initialize()
- . = ..()
- fix_noid_research_servers()
-
/proc/fix_noid_research_servers()
var/list/no_id_servers = list()
var/list/server_ids = list()
- for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
+ for(var/obj/machinery/rnd/server/S in GLOB.machines)
switch(S.server_id)
if(-1)
continue
@@ -146,7 +99,7 @@
else
server_ids += S.server_id
- for(var/obj/machinery/r_n_d/server/S in no_id_servers)
+ for(var/obj/machinery/rnd/server/S in no_id_servers)
var/num = 1
while(!S.server_id)
if(num in server_ids)
@@ -156,9 +109,6 @@
server_ids += num
no_id_servers -= S
-/obj/machinery/r_n_d/server/centcom/process()
- return PROCESS_KILL //don't need process()
-
/obj/machinery/computer/rdservercontrol
name = "R&D Server Controller"
@@ -166,7 +116,7 @@
icon_screen = "rdcomp"
icon_keyboard = "rd_key"
var/screen = 0
- var/obj/machinery/r_n_d/server/temp_server
+ var/obj/machinery/rnd/server/temp_server
var/list/servers = list()
var/list/consoles = list()
var/badmin = 0
@@ -185,58 +135,6 @@
if(href_list["main"])
screen = 0
- else if(href_list["access"] || href_list["data"] || href_list["transfer"])
- temp_server = null
- consoles = list()
- servers = list()
- for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
- if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"]))
- temp_server = S
- break
- if(href_list["access"])
- screen = 1
- for(var/obj/machinery/computer/rdconsole/C in GLOB.machines)
- if(C.sync)
- consoles += C
- else if(href_list["data"])
- screen = 2
- else if(href_list["transfer"])
- screen = 3
- for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
- if(S == src)
- continue
- servers += S
-
- else if(href_list["upload_toggle"])
- var/num = text2num(href_list["upload_toggle"])
- if(num in temp_server.id_with_upload)
- temp_server.id_with_upload -= num
- else
- temp_server.id_with_upload += num
-
- else if(href_list["download_toggle"])
- var/num = text2num(href_list["download_toggle"])
- if(num in temp_server.id_with_download)
- temp_server.id_with_download -= num
- else
- temp_server.id_with_download += num
-
- else if(href_list["reset_tech"])
- var/choice = alert("Technology Data Reset", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel")
- if(choice == "Continue" && usr.canUseTopic(src))
- var/datum/tech/T = temp_server.files.known_tech[href_list["reset_tech"]]
- if(T)
- T.level = 1
- temp_server.files.RefreshResearch()
-
- else if(href_list["reset_design"])
- var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? Data lost cannot be recovered.", "Continue", "Cancel")
- if(choice == "Continue" && usr.canUseTopic(src))
- var/datum/design/D = temp_server.files.known_designs[href_list["reset_design"]]
- if(D)
- temp_server.files.known_designs -= D.id
- temp_server.files.RefreshResearch()
-
updateUsrDialog()
return
@@ -250,58 +148,12 @@
if(0) //Main Menu
dat += "Connected Servers:
"
- for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
- if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
- continue
+ for(var/obj/machinery/rnd/server/S in GLOB.machines)
dat += "[S.name] || "
- dat += "
Access Rights | "
- dat += "
Data Management"
- if(badmin)
- dat += " |
Server-to-Server Transfer"
dat += "
"
- if(1) //Access rights menu
- dat += "[temp_server.name] Access Rights
"
- dat += "Consoles with Upload Access
"
- for(var/obj/machinery/computer/rdconsole/C in consoles)
- var/turf/console_turf = get_turf(C)
- dat += "*
[console_turf.loc]" //FYI, these are all numeric ids, eventually.
- if(C.id in temp_server.id_with_upload)
- dat += " (Remove)"
- else
- dat += " (Add)
"
- dat += "Consoles with Download Access
"
- for(var/obj/machinery/computer/rdconsole/C in consoles)
- var/turf/console_turf = get_turf(C)
- dat += "*
[console_turf.loc]"
- if(C.id in temp_server.id_with_download)
- dat += " (Remove)"
- else
- dat += " (Add)
"
- dat += "
Main Menu"
+ //Mining status here
- if(2) //Data Management menu
- dat += "[temp_server.name] Data ManagementP
"
- dat += "Known Technologies
"
- for(var/v in temp_server.files.known_tech)
- var/datum/tech/T = temp_server.files.known_tech[v]
- if(T.level <= 0)
- continue
- dat += "* [T.name] "
- dat += "
(Reset)" //FYI, these are all strings.
- dat += "Known Designs
"
- for(var/v in temp_server.files.known_designs)
- var/datum/design/D = temp_server.files.known_designs[v]
- dat += "* [D.name] "
- dat += "
(Delete)"
- dat += "
Main Menu"
-
- if(3) //Server Data Transfer
- dat += "[temp_server.name] Server to Server Transfer
"
- dat += "Send Data to what server?
"
- for(var/obj/machinery/r_n_d/server/S in servers)
- dat += "[S.name]
(Transfer)"
- dat += "
Main Menu"
user << browse("
R&D Server Control
[dat]", "window=server_control;size=575x400")
onclose(user, "server_control")
return
@@ -317,15 +169,3 @@
emagged = TRUE
to_chat(user, "
You you disable the security protocols.")
-/obj/machinery/r_n_d/server/robotics
- name = "Robotics R&D Server"
- id_with_upload_string = "1;2"
- id_with_download_string = "1;2"
- server_id = 2
-
-
-/obj/machinery/r_n_d/server/core
- name = "Core R&D Server"
- id_with_upload_string = "1"
- id_with_download_string = "1"
- server_id = 1
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index 794c975b46..af1dc853d8 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -82,39 +82,35 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
//Rating 1
+
/obj/item/stock_parts/capacitor
name = "capacitor"
desc = "A basic capacitor used in the construction of a variety of devices."
icon_state = "capacitor"
- origin_tech = "powerstorage=1"
materials = list(MAT_METAL=50, MAT_GLASS=50)
/obj/item/stock_parts/scanning_module
name = "scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "scan_module"
- origin_tech = "magnets=1"
materials = list(MAT_METAL=50, MAT_GLASS=20)
/obj/item/stock_parts/manipulator
name = "micro-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "micro_mani"
- origin_tech = "materials=1;programming=1"
materials = list(MAT_METAL=30)
/obj/item/stock_parts/micro_laser
name = "micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "micro_laser"
- origin_tech = "magnets=1"
materials = list(MAT_METAL=10, MAT_GLASS=20)
/obj/item/stock_parts/matter_bin
name = "matter bin"
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "matter_bin"
- origin_tech = "materials=1"
materials = list(MAT_METAL=80)
//Rating 2
@@ -123,7 +119,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "advanced capacitor"
desc = "An advanced capacitor used in the construction of a variety of devices."
icon_state = "adv_capacitor"
- origin_tech = "powerstorage=3"
rating = 2
materials = list(MAT_METAL=50, MAT_GLASS=50)
@@ -131,7 +126,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "advanced scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "adv_scan_module"
- origin_tech = "magnets=3"
rating = 2
materials = list(MAT_METAL=50, MAT_GLASS=20)
@@ -139,7 +133,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "nano-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "nano_mani"
- origin_tech = "materials=3;programming=2"
rating = 2
materials = list(MAT_METAL=30)
@@ -147,7 +140,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "high-power micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "high_micro_laser"
- origin_tech = "magnets=3"
rating = 2
materials = list(MAT_METAL=10, MAT_GLASS=20)
@@ -155,7 +147,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "advanced matter bin"
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "advanced_matter_bin"
- origin_tech = "materials=3"
rating = 2
materials = list(MAT_METAL=80)
@@ -165,7 +156,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "super capacitor"
desc = "A super-high capacity capacitor used in the construction of a variety of devices."
icon_state = "super_capacitor"
- origin_tech = "powerstorage=4;engineering=4"
rating = 3
materials = list(MAT_METAL=50, MAT_GLASS=50)
@@ -173,7 +163,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "phasic scanning module"
desc = "A compact, high resolution phasic scanning module used in the construction of certain devices."
icon_state = "super_scan_module"
- origin_tech = "magnets=4;engineering=4"
rating = 3
materials = list(MAT_METAL=50, MAT_GLASS=20)
@@ -181,7 +170,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "pico-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "pico_mani"
- origin_tech = "materials=4;programming=4;engineering=4"
rating = 3
materials = list(MAT_METAL=30)
@@ -189,7 +177,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "ultra-high-power micro-laser"
icon_state = "ultra_high_micro_laser"
desc = "A tiny laser used in certain devices."
- origin_tech = "magnets=4;engineering=4"
rating = 3
materials = list(MAT_METAL=10, MAT_GLASS=20)
@@ -197,7 +184,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "super matter bin"
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "super_matter_bin"
- origin_tech = "materials=4;engineering=4"
rating = 3
materials = list(MAT_METAL=80)
@@ -207,7 +193,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "quadratic capacitor"
desc = "An capacity capacitor used in the construction of a variety of devices."
icon_state = "quadratic_capacitor"
- origin_tech = "powerstorage=5;materials=4;engineering=4"
rating = 4
materials = list(MAT_METAL=50, MAT_GLASS=50)
@@ -215,7 +200,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "triphasic scanning module"
desc = "A compact, ultra resolution triphasic scanning module used in the construction of certain devices."
icon_state = "triphasic_scan_module"
- origin_tech = "magnets=5;materials=4;engineering=4"
rating = 4
materials = list(MAT_METAL=50, MAT_GLASS=20)
@@ -223,7 +207,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "femto-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "femto_mani"
- origin_tech = "materials=6;programming=4;engineering=4"
rating = 4
materials = list(MAT_METAL=30)
@@ -231,7 +214,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "quad-ultra micro-laser"
icon_state = "quadultra_micro_laser"
desc = "A tiny laser used in certain devices."
- origin_tech = "magnets=5;materials=4;engineering=4"
rating = 4
materials = list(MAT_METAL=10, MAT_GLASS=20)
@@ -239,7 +221,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "bluespace matter bin"
desc = "A container designed to hold compressed matter awaiting reconstruction."
icon_state = "bluespace_matter_bin"
- origin_tech = "materials=6;programming=4;engineering=4"
rating = 4
materials = list(MAT_METAL=80)
@@ -249,49 +230,42 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
name = "subspace ansible"
icon_state = "subspace_ansible"
desc = "A compact module capable of sensing extradimensional activity."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=1"
materials = list(MAT_METAL=30, MAT_GLASS=10)
/obj/item/stock_parts/subspace/filter
name = "hyperwave filter"
icon_state = "hyperwave_filter"
desc = "A tiny device capable of filtering and converting super-intense radiowaves."
- origin_tech = "programming=2;magnets=2"
materials = list(MAT_METAL=30, MAT_GLASS=10)
/obj/item/stock_parts/subspace/amplifier
name = "subspace amplifier"
icon_state = "subspace_amplifier"
desc = "A compact micro-machine capable of amplifying weak subspace transmissions."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=2"
materials = list(MAT_METAL=30, MAT_GLASS=10)
/obj/item/stock_parts/subspace/treatment
name = "subspace treatment disk"
icon_state = "treatment_disk"
desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=2"
materials = list(MAT_METAL=30, MAT_GLASS=10)
/obj/item/stock_parts/subspace/analyzer
name = "subspace wavelength analyzer"
icon_state = "wavelength_analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
- origin_tech = "programming=2;magnets=2;materials=2;bluespace=2"
materials = list(MAT_METAL=30, MAT_GLASS=10)
/obj/item/stock_parts/subspace/crystal
name = "ansible crystal"
icon_state = "ansible_crystal"
desc = "A crystal made from pure glass used to transmit laser databursts to subspace."
- origin_tech = "magnets=2;materials=2;bluespace=2;plasmatech=2"
materials = list(MAT_GLASS=50)
/obj/item/stock_parts/subspace/transmitter
name = "subspace transmitter"
icon_state = "subspace_transmitter"
desc = "A large piece of equipment used to open a window into the subspace dimension."
- origin_tech = "magnets=2;materials=2;bluespace=2"
materials = list(MAT_METAL=50)
/obj/item/research//Makes testing much less of a pain -Sieve
@@ -299,4 +273,3 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
icon = 'icons/obj/stock_parts.dmi'
icon_state = "capacitor"
desc = "A debug item for research."
- origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8;engineering=8;plasmatech=8;abductor=8"
diff --git a/code/modules/research/techweb/__techweb_helpers.dm b/code/modules/research/techweb/__techweb_helpers.dm
new file mode 100644
index 0000000000..adfa5c78d0
--- /dev/null
+++ b/code/modules/research/techweb/__techweb_helpers.dm
@@ -0,0 +1,178 @@
+
+/proc/initialize_all_techweb_nodes(clearall = FALSE)
+ if(islist(SSresearch.techweb_nodes) && clearall)
+ QDEL_LIST(SSresearch.techweb_nodes)
+ if(islist(SSresearch.techweb_nodes_starting && clearall))
+ QDEL_LIST(SSresearch.techweb_nodes_starting)
+ 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!")
+ SSresearch.errored_datums[TN] = initial(TN.id)
+ continue
+ returned[initial(TN.id)] = TN
+ if(TN.starting_node)
+ SSresearch.techweb_nodes_starting[TN.id] = TN
+ SSresearch.techweb_nodes = returned
+ verify_techweb_nodes() //Verify all nodes have ids and such.
+ calculate_techweb_nodes()
+ calculate_techweb_boost_list()
+ verify_techweb_nodes() //Verify nodes and designs have been crosslinked properly.
+
+/proc/initialize_all_techweb_designs(clearall = FALSE)
+ if(islist(SSresearch.techweb_designs) && clearall)
+ QDEL_LIST(SSresearch.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!")
+ SSresearch.errored_datums[DN] = initial(DN.id)
+ continue
+ returned[initial(DN.id)] = DN
+ SSresearch.techweb_designs = returned
+ verify_techweb_designs()
+
+/proc/count_unique_techweb_nodes()
+ var/static/list/L = typesof(/datum/techweb_node)
+ return L.len
+
+/proc/count_unique_techweb_designs()
+ var/static/list/L = typesof(/datum/design)
+ return L.len
+
+/proc/get_techweb_node_by_id(id)
+ if(SSresearch.techweb_nodes[id])
+ return SSresearch.techweb_nodes[id]
+
+/proc/get_techweb_design_by_id(id)
+ if(SSresearch.techweb_designs[id])
+ return SSresearch.techweb_designs[id]
+
+/proc/research_node_id_error(id)
+ if(SSresearch.invalid_node_ids[id])
+ SSresearch.invalid_node_ids[id]++
+ else
+ SSresearch.invalid_node_ids[id] = 1
+
+/proc/design_id_error(id)
+ if(SSresearch.invalid_design_ids[id])
+ SSresearch.invalid_design_ids[id]++
+ else
+ SSresearch.invalid_design_ids[id] = 1
+
+/proc/node_boost_error(id, message)
+ SSresearch.invalid_node_boost[id] = message
+
+/proc/verify_techweb_nodes()
+ for(var/n in SSresearch.techweb_nodes)
+ var/datum/techweb_node/N = SSresearch.techweb_nodes[n]
+ if(!istype(N))
+ stack_trace("WARNING: Invalid research node with ID [n] detected and removed.")
+ SSresearch.techweb_nodes -= n
+ research_node_id_error(n)
+ for(var/p in N.prereq_ids)
+ var/datum/techweb_node/P = SSresearch.techweb_nodes[p]
+ if(!istype(P))
+ stack_trace("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)
+ for(var/d in N.design_ids)
+ var/datum/design/D = SSresearch.techweb_designs[d]
+ if(!istype(D))
+ stack_trace("WARNING: Invalid research design with ID [d] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.designs -= d
+ design_id_error(d)
+ for(var/p in N.prerequisites)
+ var/datum/techweb_node/P = N.prerequisites[p]
+ if(!istype(P))
+ stack_trace("WARNING: Invalid research prerequisite node with ID [p] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.prerequisites -= p
+ research_node_id_error(p)
+ for(var/u in N.unlocks)
+ var/datum/techweb_node/U = N.unlocks[u]
+ if(!istype(U))
+ stack_trace("WARNING: Invalid research unlock node with ID [u] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.unlocks -= u
+ research_node_id_error(u)
+ for(var/d in N.designs)
+ var/datum/design/D = N.designs[d]
+ if(!istype(D))
+ stack_trace("WARNING: Invalid research design with ID [d] detected in node [N.display_name]\[[N.id]\] removed.")
+ N.designs -= d
+ design_id_error(d)
+ for(var/p in N.boost_item_paths)
+ if(!ispath(p))
+ N.boost_item_paths -= p
+ node_boost_error(N.id, "[p] is not a valid path.")
+ var/num = N.boost_item_paths[p]
+ if(!isnum(num))
+ N.boost_item_paths -= p
+ node_boost_error(N.id, "[num] is not a valid number.")
+ CHECK_TICK
+
+/proc/verify_techweb_designs()
+ for(var/d in SSresearch.techweb_designs)
+ var/datum/design/D = SSresearch.techweb_designs[d]
+ if(!istype(D))
+ stack_trace("WARNING: Invalid research design with ID [d] detected and removed.")
+ SSresearch.techweb_designs -= d
+ CHECK_TICK
+
+/proc/calculate_techweb_nodes()
+ for(var/node_id in SSresearch.techweb_nodes)
+ var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
+ node.prerequisites = list()
+ node.unlocks = list()
+ node.designs = list()
+ for(var/i in node.prereq_ids)
+ node.prerequisites[i] = SSresearch.techweb_nodes[i]
+ for(var/i in node.design_ids)
+ node.designs[i] = SSresearch.techweb_designs[i]
+ if(node.hidden)
+ SSresearch.techweb_nodes_hidden[node.id] = node
+ CHECK_TICK
+ generate_techweb_unlock_linking()
+
+/proc/generate_techweb_unlock_linking()
+ for(var/node_id in SSresearch.techweb_nodes) //Clear all unlock links to avoid duplication.
+ var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
+ node.unlocks = list()
+ for(var/node_id in SSresearch.techweb_nodes)
+ var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
+ for(var/prereq_id in node.prerequisites)
+ var/datum/techweb_node/prereq_node = node.prerequisites[prereq_id]
+ prereq_node.unlocks[node.id] = node
+
+/proc/calculate_techweb_boost_list(clearall = FALSE)
+ if(clearall)
+ SSresearch.techweb_boost_items = list()
+ for(var/node_id in SSresearch.techweb_nodes)
+ var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
+ for(var/path in node.boost_item_paths)
+ if(!ispath(path))
+ continue
+ if(length(SSresearch.techweb_boost_items[path]))
+ SSresearch.techweb_boost_items[path] += list(node.id = node.boost_item_paths[path])
+ else
+ SSresearch.techweb_boost_items[path] = list(node.id = node.boost_item_paths[path])
+ CHECK_TICK
+
+/proc/techweb_item_boost_check(obj/item/I) //Returns an associative list of techweb node datums with values of the boost it gives. var/list/returned = list()
+ if(SSresearch.techweb_boost_items[I.type])
+ return SSresearch.techweb_boost_items[I.type] //It should already be formatted in node datum = value.
+
+/proc/techweb_item_point_check(obj/item/I)
+ if(SSresearch.techweb_point_items[I.type])
+ return SSresearch.techweb_point_items[I.type]
+ return 0
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
new file mode 100644
index 0000000000..74ace7e4c2
--- /dev/null
+++ b/code/modules/research/techweb/_techweb.dm
@@ -0,0 +1,273 @@
+
+//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/datum/techweb_node/researched_nodes = list() //Already unlocked and all designs are now available. Assoc list, id = datum
+ var/list/datum/techweb_node/visible_nodes = list() //Visible nodes, doesn't mean it can be researched. Assoc list, id = datum
+ var/list/datum/techweb_node/available_nodes = list() //Nodes that can immediately be researched, all reqs met. assoc list, id = datum
+ var/list/datum/design/researched_designs = list() //Designs that are available for use. Assoc list, id = datum
+ var/list/datum/techweb_node/boosted_nodes = list() //Already boosted nodes that can't be boosted again. node datum = path of boost object.
+ var/list/datum/techweb_node/hidden_nodes = list() //Hidden nodes. id = datum. 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
+ var/research_points = 0 //Available research points.
+ var/list/obj/machinery/computer/rdconsole/consoles_accessing = list()
+ var/id = "generic"
+ var/list/research_logs = list() //IC logs.
+ var/max_bomb_value = 0
+
+/datum/techweb/New()
+ for(var/i in SSresearch.techweb_nodes_starting)
+ var/datum/techweb_node/DN = SSresearch.techweb_nodes_starting[i]
+ research_node(DN, TRUE, FALSE)
+ hidden_nodes = SSresearch.techweb_nodes_hidden
+ return ..()
+
+/datum/techweb/admin
+ research_points = INFINITY //KEKKLES.
+ id = "ADMIN"
+
+/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)
+ hidden_nodes = list()
+
+/datum/techweb/science //Global science techweb for RND consoles.
+ id = "SCIENCE"
+
+/datum/techweb/Destroy()
+ researched_nodes = null
+ researched_designs = null
+ available_nodes = null
+ visible_nodes = null
+ return ..()
+
+/datum/techweb/proc/recalculate_nodes(recalculate_designs = FALSE)
+ var/list/datum/techweb_node/processing = list()
+ for(var/i in researched_nodes)
+ processing[i] = researched_nodes[i]
+ for(var/i in visible_nodes)
+ processing[i] = visible_nodes[i]
+ for(var/i in available_nodes)
+ processing[i] = available_nodes[i]
+ for(var/i in processing)
+ update_node_status(processing[i])
+ if(recalculate_designs) //Wipes custom added designs like from design disks or anything like that!
+ researched_designs = list()
+ for(var/i in processing)
+ var/datum/techweb_node/TN = processing[i]
+ update_node_status(TN, FALSE)
+ CHECK_TICK
+ for(var/v in consoles_accessing)
+ var/obj/machinery/computer/rdconsole/V = v
+ V.rescan_views()
+ V.updateUsrDialog()
+
+/datum/techweb/proc/copy_research_to(datum/techweb/reciever, unlock_hidden = TRUE) //Adds any missing research to theirs.
+ for(var/i in researched_nodes)
+ CHECK_TICK
+ reciever.research_node_id(i, TRUE, FALSE)
+ for(var/i in researched_designs)
+ CHECK_TICK
+ reciever.add_design_by_id(i)
+ if(unlock_hidden)
+ for(var/i in reciever.hidden_nodes)
+ CHECK_TICK
+ if(!hidden_nodes[i])
+ reciever.hidden_nodes -= i //We can see it so let them see it too.
+ reciever.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_design_by_id(id)
+ return add_design(get_techweb_design_by_id(id))
+
+/datum/techweb/proc/add_design(datum/design/design)
+ if(!istype(design))
+ return FALSE
+ researched_designs[design.id] = design
+ return TRUE
+
+/datum/techweb/proc/remove_design_by_id(id)
+ return remove_design(get_techweb_design_by_id(id))
+
+/datum/techweb/proc/remove_design(datum/design/design)
+ if(!istype(design))
+ return FALSE
+ researched_designs -= design.id
+ return TRUE
+
+/datum/techweb/proc/research_node_id(id, force, auto_update_points)
+ return research_node(get_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 && (research_points < node.get_price(src))))
+ return FALSE
+ if(auto_adjust_cost)
+ research_points -= node.get_price(src)
+ researched_nodes[node.id] = node //Add to our researched list
+ for(var/i in node.unlocks)
+ visible_nodes[i] = node.unlocks[i]
+ update_node_status(node.unlocks[i])
+ for(var/i in node.designs)
+ add_design(node.designs[i])
+ update_node_status(node)
+ return TRUE
+
+/datum/techweb/proc/unresearch_node_id(id)
+ return unresearch_node(get_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
+ var/boost = N.boost_item_paths[itempath]
+ if(!boosted_nodes[N])
+ boosted_nodes[N] = boost
+ if(N.autounlock_by_boost)
+ hidden_nodes -= N.id
+ return TRUE
+
+/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/i in node.prereq_ids)
+ if(researched_nodes[i])
+ 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] = node
+ for(var/i in node.designs)
+ add_design(node.designs[i])
+ else
+ if(available)
+ available_nodes[node.id] = node
+ else
+ if(visible)
+ visible_nodes[node.id] = 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 = researched_nodes[i]
+ for(var/I in N.designs)
+ if(D == N.designs[I])
+ return TRUE
+ return FALSE
+
+/datum/techweb/proc/isDesignResearched(datum/design/D)
+ return isDesignResearchedID(D.id)
+
+/datum/techweb/proc/isDesignResearchedID(id)
+ return researched_designs[id]
+
+/datum/techweb/proc/isNodeResearched(datum/techweb_node/N)
+ return isNodeResearchedID(N.id)
+
+/datum/techweb/proc/isNodeResearchedID(id)
+ return researched_nodes[id]
+
+/datum/techweb/proc/isNodeVisible(datum/techweb_node/N)
+ return isNodeResearchedID(N.id)
+
+/datum/techweb/proc/isNodeVisibleID(id)
+ return visible_nodes[id]
+
+/datum/techweb/proc/isNodeAvailable(datum/techweb_node/N)
+ return isNodeAvailableID(N.id)
+
+/datum/techweb/proc/isNodeAvailableID(id)
+ return available_nodes[id]
+
+/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_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_designs[id]
+ if(D.build_type & design_autounlock_buildtypes)
+ for(var/i in D.category)
+ if(i in design_autounlock_categories)
+ add_design(D)
+ break
+
+/datum/techweb/specialized/autounlocking/autolathe
+ design_autounlock_buildtypes = AUTOLATHE
+ allowed_buildtypes = AUTOLATHE
+
+/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
+ node_autounlock_ids = list("robotics", "mmi", "cyborg", "mecha_odysseus", "mech_gygax", "mech_durand", "mecha_phazon", "mecha", "mech_tools", "clown")
+ allowed_buildtypes = MECHFAB
diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm
new file mode 100644
index 0000000000..75faf07bf1
--- /dev/null
+++ b/code/modules/research/techweb/_techweb_node.dm
@@ -0,0 +1,30 @@
+
+//Techweb nodes are GLOBAL, there should only be one instance of them in the game. Persistant changes should never be made to them in-game.
+
+/datum/techweb_node
+ var/id
+ var/display_name = "Errored Node"
+ var/description = "Why are you seeing this?"
+ var/hidden = FALSE //Whether it starts off hidden.
+ var/starting_node = FALSE //Whether it's available without any research.
+ var/list/prereq_ids = list()
+ var/list/design_ids = list()
+ var/list/datum/techweb_node/prerequisites = list() //Assoc list id = datum
+ var/list/datum/techweb_node/unlocks = list() //CALCULATED FROM OTHER NODE'S PREREQUISITES. Assoc list id = datum.
+ var/list/datum/design/designs = list() //Assoc list id = datum
+ var/list/boost_item_paths = list() //Associative list, path = point_value.
+ var/autounlock_by_boost = TRUE //boosting this will autounlock this node.
+ var/export_price = 0 //Cargo export price.
+ var/research_cost = 0 //Point cost to research.
+ var/actual_cost = 0
+ var/category = "Misc" //Category
+
+/datum/techweb_node/New()
+ actual_cost = research_cost
+
+/datum/techweb_node/proc/get_price(datum/techweb/host)
+ if(!host)
+ return actual_cost
+ var/discount = boost_item_paths[host.boosted_nodes[src]]
+ actual_cost = research_cost - discount
+ return actual_cost
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
new file mode 100644
index 0000000000..96b252854b
--- /dev/null
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -0,0 +1,860 @@
+
+//Current rate: 132500 research points in 90 minutes
+//Current cargo price: 250000 points for fullmaxed R&D.
+
+//Base Node
+/datum/techweb_node/base
+ id = "base"
+ starting_node = TRUE
+ display_name = "Basic Research Technology"
+ description = "NT default research technologies."
+ design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani",
+ "destructive_analyzer", "protolathe", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
+ "space_heater") //Default research tech, prevents bricking
+
+/////////////////////////Biotech/////////////////////////
+/datum/techweb_node/biotech
+ id = "biotech"
+ display_name = "Biological Technology"
+ description = "What makes us tick." //the MC, silly!
+ prereq_ids = list("base")
+ design_ids = list("mass_spectrometer", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "pandemic")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_biotech
+ id = "adv_biotech"
+ display_name = "Advanced Biotechnology"
+ description = "Advanced Biotechnology"
+ prereq_ids = list("biotech")
+ design_ids = list("piercesyringe", "adv_mass_spectrometer", "plasmarefiller", "limbgrower")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////data theory tech/////////////////////////
+/datum/techweb_node/datatheory //Computer science
+ id = "datatheory"
+ display_name = "Data Theory"
+ description = "Big Data, in space!"
+ prereq_ids = list("base")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_datatheory
+ id = "adv_datatheory"
+ display_name = "Advanced Data Theory"
+ description = "Better insight into programming and data."
+ prereq_ids = list("datatheory")
+ design_ids = list("icprinter", "icupgadv", "icupgclo")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////engineering tech/////////////////////////
+/datum/techweb_node/engineering
+ id = "engineering"
+ description = "Modern Engineering Technology."
+ display_name = "Industrial Engineering"
+ prereq_ids = list("base")
+ design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin",
+ "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "weldingmask", "mesons", "thermomachine", "tesla_coil", "grounding_rod", "apc_control")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_engi
+ id = "adv_engi"
+ description = "Advanced Engineering research"
+ display_name = "Advanced Engineering"
+ prereq_ids = list("engineering", "emp_basic")
+ design_ids = list("engine_goggles", "diagnostic_hud", "magboots")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////Bluespace tech/////////////////////////
+/datum/techweb_node/bluespace_basic //Bluespace-memery
+ id = "bluespace_basic"
+ display_name = "Basic Bluespace Theory"
+ description = "Basic studies into the mysterious alternate dimension known as bluespace."
+ prereq_ids = list("base")
+ design_ids = list("beacon", "xenobioconsole")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_bluespace
+ id = "adv_bluespace"
+ display_name = "Advanced Bluespace Research"
+ description = "Deeper understanding of how the Bluespace dimension works"
+ prereq_ids = list("practical_bluespace", "high_efficiency")
+ design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "tele_station", "tele_hub", "quantumpad", "launchpad", "launchpad_console",
+ "teleconsole", "bag_holding", "bluespace_crystal", "wormholeprojector")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////plasma tech/////////////////////////
+/datum/techweb_node/basic_plasma
+ id = "basic_plasma"
+ display_name = "Basic Plasma Research"
+ description = "Research into the mysterious and dangerous substance, plasma."
+ prereq_ids = list("engineering")
+ design_ids = list("mech_generator")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_plasma
+ id = "adv_plasma"
+ display_name = "Advanced Plasma Research"
+ description = "Research on how to fully exploit the power of plasma."
+ prereq_ids = list("basic_plasma")
+ design_ids = list("mech_plasma_cutter")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////robotics tech/////////////////////////
+/datum/techweb_node/robotics
+ id = "robotics"
+ display_name = "Basic Robotics Research"
+ description = "Programmable machines that make our lives lazier."
+ prereq_ids = list("base")
+ design_ids = list("paicard", "drone_shell")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_robotics
+ id = "adv_robotics"
+ display_name = "Advanced Robotics Research"
+ description = "It can even do the dishes!"
+ prereq_ids = list("robotics")
+ design_ids = list("borg_upgrade_diamonddrill")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////EMP tech/////////////////////////
+/datum/techweb_node/emp_basic //EMP tech for some reason
+ id = "emp_basic"
+ display_name = "Electromagnetic Theory"
+ description = "Study into usage of frequencies in the electromagnetic spectrum."
+ prereq_ids = list("base")
+ design_ids = list("holosign", "inducer", "tray_goggles", "holopad")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/emp_adv
+ id = "emp_adv"
+ display_name = "Advanced Electromagnetic Theory"
+ prereq_ids = list("emp_basic")
+ design_ids = list("ultra_micro_laser")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/emp_super
+ id = "emp_super"
+ display_name = "Quantum Electromagnetic Technology" //bs
+ description = "Even better electromagnetic technology"
+ prereq_ids = list("emp_adv")
+ design_ids = list("quadultra_micro_laser")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////Clown tech/////////////////////////
+/datum/techweb_node/clown
+ id = "clown"
+ display_name = "Clown Technology"
+ description = "Honk?!"
+ prereq_ids = list("base")
+ design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm",
+ "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////Computer tech////////////////////////
+/datum/techweb_node/comptech
+ id = "comptech"
+ display_name = "Computer Consoles"
+ description = "Computers and how they work."
+ prereq_ids = list("datatheory")
+ design_ids = list("cargo", "cargorequest", "stockexchange", "libraryconsole", "aifixer", "mining", "crewconsole", "comconsole", "idcardconsole", "operating", "seccamera")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get.
+ id = "computer_hardware_basic"
+ display_name = "Computer Hardware"
+ description = "How computer hardware are made."
+ prereq_ids = list("comptech")
+ research_cost = 2500
+ export_price = 10000
+ design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired",
+ "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced",
+ "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small")
+
+/datum/techweb_node/computer_board_gaming
+ id = "computer_board_gaming"
+ display_name = "Arcade Games"
+ description = "For the slackers on the station."
+ prereq_ids = list("comptech")
+ design_ids = list("arcade_battle", "arcade_orion", "slotmachine")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/comp_recordkeeping
+ id = "comp_recordkeeping"
+ display_name = "Computerized Recordkeeping"
+ description = "Organized record databases and how they're used."
+ prereq_ids = list("comptech")
+ design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/telecomms
+ id = "telecomms"
+ display_name = "Telecommunications Technology"
+ description = "Subspace transmission technology for near-instant communications devices."
+ prereq_ids = list("comptech", "bluespace_basic")
+ research_cost = 2500
+ export_price = 10000
+ design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server",
+ "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter")
+
+/datum/techweb_node/integrated_HUDs
+ id = "integrated_HUDs"
+ display_name = "Integrated HUDs"
+ description = "The usefulness of computerized records, projected straight onto your eyepiece!"
+ prereq_ids = list("comp_recordkeeping", "emp_basic")
+ design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/NVGtech
+ id = "NVGtech"
+ display_name = "Night Vision Technology"
+ description = "Allows seeing in the dark without actual light!"
+ prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv")
+ design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////AI & Cyborg tech////////////////////////
+/datum/techweb_node/neural_programming
+ id = "neural_programming"
+ display_name = "Neural Programming"
+ description = "Study into networks of processing units that mimic our brains."
+ prereq_ids = list("biotech", "datatheory")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mmi
+ id = "mmi"
+ display_name = "Man Machine Interface"
+ description = "A slightly Frankensteinian device that allows human brains to interface natively with software APIs."
+ prereq_ids = list("biotech", "neural_programming")
+ design_ids = list("mmi")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/posibrain
+ id = "posibrain"
+ display_name = "Positronic Brain"
+ description = "Applied usage of neural technology allowing for autonomous AI units based on special metallic cubes with conductive and processing circuits."
+ prereq_ids = list("mmi", "neural_programming")
+ design_ids = list("mmi_posi")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/cyborg
+ id = "cyborg"
+ display_name = "Cyborg Construction"
+ description = "Sapient robots with preloaded tool modules and programmable laws."
+ prereq_ids = list("mmi", "robotics")
+ research_cost = 2500
+ export_price = 10000
+ design_ids = list("robocontrol", "sflash", "borg_suit", "borg_head", "borg_chest", "borg_r_arm", "borg_l_arm", "borg_r_leg", "borg_l_leg", "borgupload",
+ "cyborgrecharger", "borg_upgrade_restart", "borg_upgrade_rename")
+
+/datum/techweb_node/cyborg_upg_util
+ id = "cyborg_upg_util"
+ display_name = "Cyborg Upgrades: Utility"
+ description = "Utility upgrades for cybogs."
+ prereq_ids = list("engineering", "cyborg")
+ design_ids = list("borg_upgrade_holding", "borg_upgrade_lavaproof", "borg_upgrade_thrusters", "borg_upgrade_selfrepair")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/cyborg_upg_med
+ id = "cyborg_upg_med"
+ display_name = "Cyborg Upgrades: Medical"
+ description = "Medical upgrades for cyborgs"
+ prereq_ids = list("adv_biotech", "cyborg")
+ design_ids = list("borg_upgrade_defibrillator", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/cyborg_upg_combat
+ id = "cyborg_upg_combat"
+ display_name = "Cyborg Upgrades: Combat"
+ description = "Military grade upgrades for cyborgs."
+ prereq_ids = list("adv_robotics", "adv_engi")
+ design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/ai
+ id = "ai"
+ display_name = "Artificial Intelligence"
+ description = "AI unit research."
+ prereq_ids = list("robotics", "neural_programming")
+ design_ids = list("aicore", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module",
+ "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "paladin_module", "tyrant_module", "corporate_module",
+ "default_module", "borg_ai_control", "mecha_tracking_ai_control", "aiupload", "intellicard")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////Medical////////////////////////
+/datum/techweb_node/cloning
+ id = "cloning"
+ display_name = "Genetic Engineering"
+ description = "We have the technology to make him."
+ prereq_ids = list("biotech")
+ design_ids = list("clonecontrol", "clonepod", "clonescanner", "scan_console")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/cryotech
+ id = "cryotech"
+ display_name = "Cryostasis Technology"
+ description = "Smart freezing of objects to preserve them!"
+ prereq_ids = list("adv_engi", "emp_basic", "biotech")
+ design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/subdermal_implants
+ id = "subdermal_implants"
+ display_name = "Subdermal Implants"
+ description = "Electronic implants buried beneath the skin."
+ prereq_ids = list("biotech")
+ design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/cyber_organs
+ id = "cyber_organs"
+ display_name = "Cybernetic Organs"
+ description = "We have the technology to rebuild him."
+ prereq_ids = list("adv_biotech", "cyborg")
+ design_ids = list("cybernetic_heart", "cybernetic_liver", "cybernetic_liver_u", "cybernetic_lungs")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/cyber_implants
+ id = "cyber_implants"
+ display_name = "Cybernetic Implants"
+ description = "Electronic implants that improve humans."
+ prereq_ids = list("adv_biotech", "cyborg", "adv_datatheory")
+ design_ids = list("ci-nutriment", "ci-nutrimentplus", "ci-breather", "ci-gloweyes", "ci-welding", "ci-medhud", "ci-sechud")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_cyber_implants
+ id = "adv_cyber_implants"
+ display_name = "Advanced Cybernetic Implants"
+ description = "Upgraded and more powerful cybernetic implants."
+ prereq_ids = list("neural_programming", "cyber_implants")
+ design_ids = list("ci-toolset", "ci-surgery", "ci-reviver")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/combat_cyber_implants
+ id = "combat_cyber_implants"
+ display_name = "Combat Cybernetic Implants"
+ description = "Military grade combat implants to improve performance."
+ prereq_ids = list("adv_cyber_implants") //Needs way more reqs.
+ design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////generic biotech////////////////////////
+/datum/techweb_node/bio_process
+ id = "bio_process"
+ display_name = "Biological Processing"
+ description = "From slimes to kitchens."
+ prereq_ids = list("biotech")
+ design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////generic engineering////////////////////////
+/datum/techweb_node/high_efficiency
+ id = "high_efficiency"
+ display_name = "High Efficiency Parts"
+ description = "High Efficiency Parts"
+ prereq_ids = list("engineering", "datatheory")
+ design_ids = list("pico_mani", "super_matter_bin")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_power
+ id = "adv_power"
+ display_name = "Advanced Power Manipulation"
+ description = "How to get more zap."
+ prereq_ids = list("engineering")
+ design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////Tools////////////////////////
+/datum/techweb_node/basic_mining
+ id = "basic_mining"
+ display_name = "Mining Technology"
+ description = "Better than Efficiency V."
+ prereq_ids = list("engineering")
+ design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_mining
+ id = "adv_mining"
+ display_name = "Advanced Mining Technology"
+ description = "Efficiency Level 127" //dumb mc references
+ prereq_ids = list("basic_mining", "adv_engi", "adv_power", "adv_plasma")
+ design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter", "plasmacutter_adv")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/practical_bluespace
+ id = "practical_bluespace"
+ display_name = "Applied Bluespace Research"
+ description = "Using bluespace to make things faster and better."
+ prereq_ids = list("bluespace_basic", "engineering")
+ design_ids = list("bs_rped","minerbag_holding", "telesci_gps", "bluespacebeaker", "bluespacesyringe", "bluespacebodybag", "phasic_scanning")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/janitor
+ id = "janitor"
+ display_name = "Advanced Sanitation Technology"
+ description = "Clean things better, faster, stronger, and harder!"
+ prereq_ids = list("adv_engi")
+ design_ids = list("advmop", "buffer", "blutrash", "light_replacer")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/botany
+ id = "botany"
+ display_name = "Botanical Engineering"
+ description = "Botanical tools"
+ prereq_ids = list("adv_engi", "biotech")
+ design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/exp_tools
+ id = "exp_tools"
+ display_name = "Experimental Tools"
+ description = "Highly advanced construction tools."
+ design_ids = list("exwelder", "jawsoflife", "handdrill")
+ prereq_ids = list("adv_engi")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/exp_equipment
+ id = "exp_equipment"
+ display_name = "Experimental Flight Equipment"
+ description = "Highly advanced construction tools."
+ design_ids = list("flightshoes", "flightpack", "flightsuit")
+ prereq_ids = list("adv_engi")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/bluespace_power
+ id = "bluespace_power"
+ display_name = "Bluespace Power Technology"
+ description = "Even more powerful.. power!"
+ prereq_ids = list("adv_power", "adv_bluespace")
+ design_ids = list("bluespace_cell", "quadratic_capacitor")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////weaponry tech/////////////////////////
+/datum/techweb_node/weaponry
+ id = "weaponry"
+ display_name = "Weapon Development Technology"
+ description = "Our researchers have found new to weaponize just about everything now."
+ prereq_ids = list("engineering")
+ design_ids = list("pin_testing")
+ research_cost = 10000
+ export_price = 10000
+
+/datum/techweb_node/adv_weaponry
+ id = "adv_weaponry"
+ display_name = "Advanced Weapon Development Technology"
+ description = "Our weapons are breaking the rules of reality by now."
+ prereq_ids = list("adv_engi", "weaponry")
+ design_ids = list("pin_loyalty")
+ research_cost = 10000
+ export_price = 10000
+
+/datum/techweb_node/electric_weapons
+ id = "electronic_weapons"
+ display_name = "Electric Weapons"
+ description = "Weapons using electric technology"
+ prereq_ids = list("weaponry", "adv_power")
+ design_ids = list("stunrevolver", "stunshell", "tele_shield")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/radioactive_weapons
+ id = "radioactive_weapons"
+ display_name = "Radioactive Weaponry"
+ description = "Weapons using radioactive technology."
+ prereq_ids = list("adv_engi", "adv_weaponry")
+ design_ids = list("nuclear_gun", "decloner")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/medical_weapons
+ id = "medical_weapons"
+ display_name = "Medical Weaponry"
+ description = "Weapons using medical technology."
+ prereq_ids = list("adv_biotech", "adv_weaponry")
+ design_ids = list("rapidsyringe")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/beam_weapons
+ id = "beam_weapons"
+ display_name = "Beam Weaponry"
+ description = "Various basic beam weapons"
+ prereq_ids = list("adv_weaponry")
+ design_ids = list("beamrifle", "ioncarbine")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_beam_weapons
+ id = "adv_beam_weapons"
+ display_name = "Advanced Beam Weaponry"
+ description = "Various advanced beam weapons"
+ prereq_ids = list("beam_weapons")
+ design_ids = list("xray_laser")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/explosive_weapons
+ id = "explosive_weapons"
+ display_name = "Explosive & Pyrotechnical Weaponry"
+ description = "If the light stuff just won't do it."
+ prereq_ids = list("adv_weaponry")
+ design_ids = list("temp_gun", "large_Grenade", "pyro_Grenade", "adv_Grenade")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/ballistic_weapons
+ id = "ballistic_weapons"
+ display_name = "Ballistic Weaponry"
+ description = "This isn't research.. This is reverse-engineering!"
+ prereq_ids = list("weaponry")
+ design_ids = list("mag_oldsmg", "mag_oldsmg_ap", "mag_oldsmg_ic")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/tech_shell
+ id = "tech_shell"
+ display_name = "Technological Shells"
+ description = "They're more technological than regular shot."
+ prereq_ids = list("adv_weaponry")
+ design_ids = list("techshotshell")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/gravity_gun
+ id = "gravity_gun"
+ display_name = "One-point Bluespace-gravitational Manipulator"
+ description = "Fancy wording for gravity gun"
+ prereq_ids = list("adv_weaponry", "adv_bluespace")
+ design_ids = list("gravitygun")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////mech technology////////////////////////
+/datum/techweb_node/mech
+ id = "mecha"
+ display_name = "Mechanical Exosuits"
+ description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human."
+ prereq_ids = list("robotics", "adv_engi")
+ design_ids = list("mecha_tracking", "mechacontrol", "mechapower", "mech_recharger", "ripley_chassis", "firefighter_chassis", "ripley_torso", "ripley_left_arm", "ripley_right_arm", "ripley_left_leg", "ripley_right_leg",
+ "ripley_main", "ripley_peri", "mech_hydraulic_clamp")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_mecha
+ id = "adv_mecha"
+ display_name = "Mechanical Exosuits"
+ description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human."
+ prereq_ids = list("adv_robotics", "mecha")
+ design_ids = list("mech_repair_droid")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/odysseus
+ id = "mecha_odysseus"
+ display_name = "EXOSUIT: Odysseus"
+ description = "Odysseus exosuit designs"
+ prereq_ids = list("mecha")
+ design_ids = list("odysseus_chassis", "odysseus_torso", "odysseus_head", "odysseus_left_arm", "odysseus_right_arm" ,"odysseus_left_leg", "odysseus_right_leg",
+ "odysseus_main", "odysseus_peri")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/gygax
+ id = "mech_gygax"
+ display_name = "EXOSUIT: Gygax"
+ description = "Gygax exosuit designs"
+ prereq_ids = list("adv_mecha", "weaponry")
+ design_ids = list("gygax_chassis", "gygax_torso", "gygax_head", "gygax_left_arm", "gygax_right_arm", "gygax_left_leg", "gygax_right_leg", "gygax_main",
+ "gygax_peri", "gygax_targ", "gygax_armor")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/durand
+ id = "mech_durand"
+ display_name = "EXOSUIT: Durand"
+ description = "Durand exosuit designs"
+ prereq_ids = list("adv_mecha", "adv_weaponry")
+ design_ids = list("durand_chassis", "durand_torso", "durand_head", "durand_left_arm", "durand_right_arm", "durand_left_leg", "durand_right_leg", "durand_main",
+ "durand_peri", "durand_targ", "durand_armor")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/phazon
+ id = "mecha_phazon"
+ display_name = "EXOSUIT: Phazon"
+ description = "Phazon exosuit designs"
+ prereq_ids = list("adv_mecha", "weaponry")
+ design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main",
+ "phazon_peri", "phazon_targ", "phazon_armor")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_tools
+ id = "mech_tools"
+ display_name = "Basic Exosuit Equipment"
+ description = "Various tools fit for basic mech units"
+ prereq_ids = list("mecha", "engineering")
+ design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_mecha_tools
+ id = "adv_mecha_tools"
+ display_name = "Advanced Exosuit Equipment"
+ description = "Tools for high level mech suits"
+ prereq_ids = list("adv_mecha", "mech_tools", "adv_engi")
+ design_ids = list("mech_rcd")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/med_mech_tools
+ id = "med_mech_tools"
+ display_name = "Medical Exosuit Equipment"
+ description = "Tools for high level mech suits"
+ prereq_ids = list("mecha", "adv_biotech", "mech_tools")
+ design_ids = list("mech_sleeper", "mech_syringe_gun", "mech_medi_beam")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_modules
+ id = "adv_mecha_modules"
+ display_name = "Basic Exosuit Modules"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("adv_mecha", "adv_power")
+ design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_scattershot
+ id = "mecha_tools"
+ display_name = "Exosuit Weapon (LBX AC 10 \"Scattershot\")"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "adv_weaponry", "ballistic_weapons")
+ design_ids = list("mech_scattershot")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_carbine
+ id = "mech_carbine"
+ display_name = "Exosuit Weapon (FNX-99 \"Hades\" Carbine)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "adv_weaponry", "ballistic_weapons")
+ design_ids = list("mech_carbine")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_ion
+ id = "mmech_ion"
+ display_name = "Exosuit Weapon (MKIV Ion Heavy Cannon)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "adv_weaponry", "emp_adv")
+ design_ids = list("mech_ion")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_tesla
+ id = "mech_tesla"
+ display_name = "Exosuit Weapon (MKI Tesla Cannon)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "weaponry", "adv_power")
+ design_ids = list("mech_tesla")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_laser
+ id = "mech_laser"
+ display_name = "Exosuit Weapon (CH-PS \"Immolator\" Laser)"
+ description = "A basic piece of mech weaponry"
+ prereq_ids = list("mecha", "beam_weapons")
+ design_ids = list("mech_laser")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_laser_heavy
+ id = "mech_laser_heavy"
+ display_name = "Exosuit Weapon (CH-LC \"Solaris\" Laser Cannon)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "adv_weaponry", "adv_beam_weapons")
+ design_ids = list("mech_laser_heavy")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_grenade_launcher
+ id = "mech_grenade_launcher"
+ display_name = "Exosuit Weapon (SGL-6 Grenade Launcher)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "explosive_weapons")
+ design_ids = list("mech_grenade_launcher")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_missile_rack
+ id = "mech_missile_rack"
+ display_name = "Exosuit Weapon (SRM-8 Missile Rack)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "explosive_weapons")
+ design_ids = list("mech_missile_rack")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/clusterbang_launcher
+ id = "clusterbang_launcher"
+ display_name = "Exosuit Module (SOB-3 Clusterbang Launcher)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "weaponry")
+ design_ids = list("clusterbang_launcher")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_teleporter
+ id = "mech_teleporter"
+ display_name = "Exosuit Module (Teleporter Module)"
+ description = "An advanced piece of mech Equipment"
+ prereq_ids = list("mecha", "mech_tools", "adv_bluespace")
+ design_ids = list("mech_teleporter")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_wormhole_gen
+ id = "mech_wormhole_gen"
+ display_name = "Exosuit Module (Localized Wormhole Generator)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("mecha", "mech_tools", "adv_bluespace")
+ design_ids = list("mech_wormhole_gen")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_taser
+ id = "mech_taser"
+ display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)"
+ description = "A basic piece of mech weaponry"
+ prereq_ids = list("mecha", "adv_weaponry")
+ design_ids = list("mech_taser")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_lmg
+ id = "mech_lmg"
+ display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)"
+ description = "An advanced piece of mech weaponry"
+ prereq_ids = list("adv_mecha", "adv_weaponry", "ballistic_weapons")
+ design_ids = list("mech_lmg")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/mech_diamond_drill
+ id = "mech_diamond_drill"
+ display_name = "Exosuit Diamond Drill"
+ description = "A diamond drill fit for a large exosuit"
+ prereq_ids = list("mecha", "adv_mining")
+ design_ids = list("mech_diamond_drill")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////Alien technology////////////////////////
+/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech
+ id = "alientech"
+ display_name = "Alien Technology"
+ description = "Things used by the greys."
+ prereq_ids = list("base")
+ boost_item_paths = list(/obj/item/gun/energy/alien = 0, /obj/item/scalpel/alien = 0, /obj/item/hemostat/alien = 0, /obj/item/retractor/alien = 0, /obj/item/circular_saw/alien = 0,
+ /obj/item/cautery/alien = 0, /obj/item/surgicaldrill/alien = 0, /obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0,
+ /obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0)
+ research_cost = 2500
+ export_price = 10000
+ hidden = TRUE
+ design_ids = list("alienalloy")
+
+/datum/techweb_node/alien_bio
+ id = "alien_bio"
+ display_name = "Alien Biological Tools"
+ description = "Advanced biological tools."
+ prereq_ids = list("alientech", "biotech")
+ design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
+ boost_item_paths = list(/obj/item/gun/energy/alien = 0, /obj/item/scalpel/alien = 0, /obj/item/hemostat/alien = 0, /obj/item/retractor/alien = 0, /obj/item/circular_saw/alien = 0,
+ /obj/item/cautery/alien = 0, /obj/item/surgicaldrill/alien = 0, /obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0,
+ /obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0)
+ research_cost = 2500
+ export_price = 10000
+ hidden = TRUE
+
+/datum/techweb_node/alien_engi
+ id = "alien_engi"
+ display_name = "Alien Engineering"
+ description = "Alien engineering tools"
+ prereq_ids = list("alientech", "adv_engi")
+ boost_item_paths = list(/obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0,
+ /obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0)
+ design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
+ research_cost = 2500
+ export_price = 10000
+ hidden = TRUE
+
+/proc/total_techweb_points()
+ var/list/datum/techweb_node/processing = list()
+ for(var/i in subtypesof(/datum/techweb_node))
+ processing += new i
+ . = 0
+ for(var/i in processing)
+ var/datum/techweb_node/TN = i
+ . += TN.research_cost
+
+/*
+/datum/design/borg_syndicate_module
+ name = "Cyborg Upgrade (Illegal Modules)"
+ id = "borg_syndicate_module"
+ construction_time = 120
+
+/datum/design/suppressor
+ name = "Universal Suppressor"
+ id = "suppressor"
+
+/datum/design/largecrossbow
+ name = "Energy Crossbow"
+ id = "largecrossbow"
+ build_path = /obj/item/gun/energy/kinetic_accelerator/crossbow/large
+*/
\ No newline at end of file
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 576ba6fe8c..ca929e5e9a 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -99,7 +99,7 @@
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
for(var/mob/living/simple_animal/slime/S in X.stored_slimes)
- S.loc = remote_eye.loc
+ S.forceMove(remote_eye.loc)
S.visible_message("[S] warps in!")
X.stored_slimes -= S
else
@@ -125,7 +125,7 @@
if(S.buckled)
S.Feedstop(silent=1)
S.visible_message("[S] vanishes in a flash of light!")
- S.loc = X
+ S.forceMove(X)
X.stored_slimes += S
else
to_chat(owner, "
Target is not near a camera. Cannot proceed.")
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index b809401ed1..93fd8dda37 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -11,8 +11,8 @@
throwforce = 0
throw_speed = 3
throw_range = 6
- origin_tech = "biotech=3"
container_type = INJECTABLE_1
+ grind_results = list()
var/Uses = 1 // uses before it goes inert
var/qdel_timer = null // deletion timer, for delayed reactions
@@ -30,6 +30,10 @@
. = ..()
create_reagents(100)
+/obj/item/slime_extract/on_grind()
+ if(Uses)
+ grind_results["slimejelly"] = 20
+
/obj/item/slime_extract/grey
name = "grey slime extract"
icon_state = "grey slime extract"
@@ -124,7 +128,6 @@
name = "slime potion"
desc = "A hard yet gelatinous capsule excreted by a slime, containing mysterious substances."
w_class = WEIGHT_CLASS_TINY
- origin_tech = "biotech=4"
/obj/item/slimepotion/afterattack(obj/item/reagent_containers/target, mob/user , proximity)
if (istype(target))
@@ -162,7 +165,6 @@
desc = "A miraculous chemical mix that grants human like intelligence to living beings."
icon = 'icons/obj/chemical.dmi'
icon_state = "potpink"
- origin_tech = "biotech=6"
var/list/not_interested = list()
var/being_used = 0
var/sentience_type = SENTIENCE_ORGANIC
@@ -208,7 +210,6 @@
desc = "A strange slime-based chemical that, when used, allows the user to transfer their consciousness to a lesser being."
icon = 'icons/obj/chemical.dmi'
icon_state = "potorange"
- origin_tech = "biotech=6"
var/prompted = 0
var/animal_type = SENTIENCE_ORGANIC
@@ -294,7 +295,7 @@
return ..()
to_chat(user, "
You feed the slime the stabilizer. It is now less likely to mutate.")
- M.mutation_chance = Clamp(M.mutation_chance-15,0,100)
+ M.mutation_chance = CLAMP(M.mutation_chance-15,0,100)
qdel(src)
/obj/item/slimepotion/mutator
@@ -318,7 +319,7 @@
return ..()
to_chat(user, "
You feed the slime the mutator. It is now more likely to mutate.")
- M.mutation_chance = Clamp(M.mutation_chance+12,0,100)
+ M.mutation_chance = CLAMP(M.mutation_chance+12,0,100)
M.mutator_used = TRUE
qdel(src)
@@ -327,7 +328,6 @@
desc = "A potent chemical mix that will remove the slowdown from any item."
icon = 'icons/obj/chemical.dmi'
icon_state = "potyellow"
- origin_tech = "biotech=5"
/obj/item/slimepotion/speed/afterattack(obj/C, mob/user)
..()
@@ -360,7 +360,6 @@
desc = "A potent chemical mix that will fireproof any article of clothing. Has three uses."
icon = 'icons/obj/chemical.dmi'
icon_state = "potblue"
- origin_tech = "biotech=5"
var/uses = 3
/obj/item/slimepotion/fireproof/afterattack(obj/item/clothing/C, mob/user)
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index 46921efc6a..126cff9713 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -33,7 +33,6 @@
name = "Golem Shell Construction"
desc = "Allows for the construction of a Golem Shell."
id = "golem"
- req_tech = list("materials" = 12)
build_type = AUTOLATHE
materials = list(MAT_METAL = 40000)
build_path = /obj/item/golem_shell
diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm
index 7f301bf8b9..f98162266a 100644
--- a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm
+++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm
@@ -9,7 +9,7 @@
faction = list("ashwalker")
health = 200
maxHealth = 200
- loot = list(/obj/effect/collapse)
+ loot = null
var/meat_counter = 6
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/death()
diff --git a/code/modules/server_tools/st_commands.dm b/code/modules/server_tools/st_commands.dm
index 9ec87a595c..1e071550e0 100644
--- a/code/modules/server_tools/st_commands.dm
+++ b/code/modules/server_tools/st_commands.dm
@@ -51,7 +51,7 @@
/*
The MIT License
-Copyright (c) 2011 Dominic Tarr
+Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/code/modules/server_tools/st_interface.dm b/code/modules/server_tools/st_interface.dm
index 39bebbbb3d..b0b1b0a43c 100644
--- a/code/modules/server_tools/st_interface.dm
+++ b/code/modules/server_tools/st_interface.dm
@@ -30,7 +30,10 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
return
if(skip_compat_check && !fexists(SERVICE_INTERFACE_DLL))
CRASH("Service parameter present but no interface DLL detected. This is symptomatic of running a service less than version 3.1! Please upgrade.")
- call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(command) //trust no retval
+ var/instance = params[SERVICE_INSTANCE_PARAM]
+ if(!instance)
+ instance = "TG Station Server" //maybe just upgraded
+ call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance, command) //trust no retval
return TRUE
/world/proc/ChatBroadcast(message)
@@ -72,7 +75,7 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
switch(command)
if(SERVICE_CMD_API_COMPATIBLE)
SERVER_TOOLS_WRITE_GLOBAL(server_tools_api_compatible, TRUE)
- return "SUCCESS"
+ return SERVICE_RETURN_SUCCESS
if(SERVICE_CMD_HARD_REBOOT)
if(SERVER_TOOLS_READ_GLOBAL(reboot_mode) != REBOOT_MODE_HARD)
SERVER_TOOLS_WRITE_GLOBAL(reboot_mode, REBOOT_MODE_HARD)
@@ -88,7 +91,7 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
if(!istext(msg) || !msg)
return "No message set!"
SERVER_TOOLS_WORLD_ANNOUNCE(msg)
- return "SUCCESS"
+ return SERVICE_RETURN_SUCCESS
if(SERVICE_CMD_PLAYER_COUNT)
return "[SERVER_TOOLS_CLIENT_COUNT]"
if(SERVICE_CMD_LIST_CUSTOM)
@@ -96,13 +99,13 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
else
var/custom_command_result = HandleServiceCustomCommand(lowertext(command), params[SERVICE_CMD_PARAM_SENDER], params[SERVICE_CMD_PARAM_CUSTOM])
if(custom_command_result)
- return istext(custom_command_result) ? custom_command_result : "SUCCESS"
+ return istext(custom_command_result) ? custom_command_result : SERVICE_RETURN_SUCCESS
return "Unknown command: [command]"
/*
The MIT License
-Copyright (c) 2011 Dominic Tarr
+Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index d573f9ce13..c4eb16305a 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -473,7 +473,7 @@
turfs -= T
T = pick(turfs)
else
- src.loc = T
+ forceMove(T)
break
//Pod suits/pickaxes
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index 65636aa528..de1b0022f6 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -119,7 +119,7 @@
return
if(!my_port)
- my_port = new /obj/docking_port/stationary()
+ my_port = new(locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z))
my_port.name = shuttlePortName
my_port.id = shuttlePortId
my_port.height = shuttle_port.height
@@ -128,7 +128,6 @@
my_port.dwidth = shuttle_port.dwidth
my_port.hidden = shuttle_port.hidden
my_port.dir = the_eye.dir
- my_port.loc = locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z)
if(current_user.client)
current_user.client.images -= the_eye.placed_images
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index 15f0dbb011..c7a77f9457 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -89,15 +89,23 @@ All ShuttleMove procs go here
return
loc = newT
+
return TRUE
// Called on atoms after everything has been moved
/atom/movable/proc/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
+
+ var/turf/newT = get_turf(src)
+ if (newT.z != oldT.z)
+ onTransitZ(oldT.z, newT.z)
+
if(light)
update_light()
if(rotation)
shuttleRotate(rotation)
+
+
update_parallax_contents()
return TRUE
@@ -328,9 +336,6 @@ All ShuttleMove procs go here
/atom/movable/lighting_object/onShuttleMove()
return FALSE
-/atom/movable/light/onShuttleMove()
- return FALSE
-
/obj/docking_port/stationary/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
if(!moving_dock.can_move_docking_ports || old_dock == src)
return FALSE
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index fa4c0fd789..3811fa0e4a 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -108,7 +108,7 @@
// realX = _x + compX*cos - compY*sin
// realY = _y + compY*cos - compX*sin
// locate(realX, realY, _z)
- var/turf/T = locate(_x + compX*cos - compY*sin, _y + compY*cos - compX*sin, _z)
+ var/turf/T = locate(_x + compX*cos - compY*sin, _y + compY*cos + compX*sin, _z)
.[T] = NONE
#ifdef DOCKING_PORT_HIGHLIGHT
@@ -146,13 +146,13 @@
var/y0 = bounds[2]
var/x1 = bounds[3]
var/y1 = bounds[4]
- if(x0 <= x1 && !IsInRange(T.x, x0, x1))
+ if(x0 <= x1 && !ISINRANGE(T.x, x0, x1))
return FALSE
- else if(!IsInRange(T.x, x1, x0))
+ else if(!ISINRANGE(T.x, x1, x0))
return FALSE
- if(y0 <= y1 && !IsInRange(T.y, y0, y1))
+ if(y0 <= y1 && !ISINRANGE(T.y, y0, y1))
return FALSE
- else if(!IsInRange(T.y, y1, y0))
+ else if(!ISINRANGE(T.y, y1, y0))
return FALSE
return TRUE
@@ -433,7 +433,7 @@
for(var/i in 1 to old_turfs.len)
var/turf/oldT = old_turfs[i]
- if(!oldT || !istype(oldT, area_type))
+ if(!oldT || !istype(oldT.loc, area_type))
continue
var/area/old_area = oldT.loc
underlying_area.contents += oldT
@@ -460,7 +460,7 @@
for(var/i in 1 to L0.len)
var/turf/T0 = L0[i]
- if(!T0 || !istype(T0, area_type))
+ if(!T0 || !istype(T0.loc, area_type))
continue
var/turf/T1 = L1[i]
if(!T1)
@@ -534,7 +534,7 @@
rotation = dir2angle(new_dock.dir)-dir2angle(dir)
if ((rotation % 90) != 0)
rotation += (rotation % 90) //diagonal rotations not allowed, round up
- rotation = SimplifyDegrees(rotation)
+ rotation = SIMPLIFY_DEGREES(rotation)
if(!movement_direction)
movement_direction = turn(preferred_direction, 180)
@@ -562,6 +562,7 @@
var/list/old_contents = oldT.contents
for(var/k in 1 to old_contents.len)
+ CHECK_TICK
var/atom/movable/moving_atom = old_contents[k]
if(moving_atom.loc != oldT) //fix for multi-tile objects
continue
@@ -575,12 +576,13 @@
old_turfs[oldT] = move_mode
- /*******************************************Hiding turfs if necessary******************************************/
+ /*******************************************Hiding turfs if necessary*******************************************/
var/list/new_hidden_turfs
if(hidden)
new_hidden_turfs = list()
for(var/i in 1 to old_turfs.len)
+ CHECK_TICK
var/turf/oldT = old_turfs[i]
if(old_turfs[oldT] & MOVE_TURF)
new_hidden_turfs += new_turfs[i]
@@ -588,6 +590,8 @@
/*******************************************All onShuttleMove procs******************************************/
+ CHECK_TICK
+
for(var/i in 1 to old_turfs.len)
var/turf/oldT = old_turfs[i]
var/turf/newT = new_turfs[i]
@@ -741,7 +745,7 @@
var/list/L0 = return_ordered_turfs(x, y, z, dir)
for (var/thing in L0)
var/turf/T = thing
- if(!T || !istype(T, area_type))
+ if(!T || !istype(T.loc, area_type))
continue
for (var/thing2 in T)
var/atom/movable/AM = thing2
@@ -884,13 +888,13 @@
var/change_per_engine = (1 - ENGINE_COEFF_MIN) / ENGINE_DEFAULT_MAXSPEED_ENGINES // 5 by default
if(initial_engines > 0)
change_per_engine = (1 - ENGINE_COEFF_MIN) / initial_engines // or however many it had
- return Clamp(1 - delta * change_per_engine,ENGINE_COEFF_MIN,ENGINE_COEFF_MAX)
+ return CLAMP(1 - delta * change_per_engine,ENGINE_COEFF_MIN,ENGINE_COEFF_MAX)
if(new_value < initial_engines)
var/delta = initial_engines - new_value
var/change_per_engine = 1 //doesn't really matter should not be happening for 0 engine shuttles
if(initial_engines > 0)
change_per_engine = (ENGINE_COEFF_MAX - 1) / initial_engines //just linear drop to max delay
- return Clamp(1 + delta * change_per_engine,ENGINE_COEFF_MIN,ENGINE_COEFF_MAX)
+ return CLAMP(1 + delta * change_per_engine,ENGINE_COEFF_MIN,ENGINE_COEFF_MAX)
/obj/docking_port/mobile/proc/in_flight()
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index b73cfb05e2..579397cc4b 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -17,7 +17,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/effect/clockwork/spatial_gateway,
/obj/structure/destructible/clockwork/powered/clockwork_obelisk,
/obj/item/device/warp_cube,
- /obj/machinery/r_n_d/protolathe, //print tracking beacons, send shuttle
+ /obj/machinery/rnd/protolathe, //print tracking beacons, send shuttle
/obj/machinery/autolathe, //same
/obj/item/projectile/beam/wormhole,
/obj/effect/portal,
diff --git a/code/modules/spells/spell_types/conjure.dm b/code/modules/spells/spell_types/conjure.dm
index 87c1b8de44..306c3fcef6 100644
--- a/code/modules/spells/spell_types/conjure.dm
+++ b/code/modules/spells/spell_types/conjure.dm
@@ -56,6 +56,18 @@
range = 3
newVars = list("emagged" = 2, "remote_disabled" = 1,"shoot_sound" = 'sound/weapons/laser.ogg',"projectile" = /obj/item/projectile/beam/laser, "declare_arrests" = 0,"name" = "Wizard's Justicebot")
+/obj/effect/proc_holder/spell/aoe_turf/conjure/linkWorlds
+ name = "Link Worlds"
+ desc = "A whole new dimension for you to play with! They won't be happy about it, though."
+ invocation = "WTF"
+ clothes_req = FALSE
+ charge_max = 600
+ cooldown_min = 200
+ summon_type = list(/mob/living/simple_animal/hostile/spawner/nether)
+ summon_amt = 1
+ range = 1
+ cast_sound = 'sound/weapons/marauder.ogg'
+
/obj/effect/proc_holder/spell/targeted/conjure_item
name = "Summon weapon"
desc = "A generic spell that should not exist. This summons an instance of a specific type of item, or if one already exists, un-summons it. Summons into hand if possible."
diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm
index 9b120c2e7f..b36dfc885d 100644
--- a/code/modules/spells/spell_types/wizard.dm
+++ b/code/modules/spells/spell_types/wizard.dm
@@ -209,7 +209,7 @@
summon_amt = 10
range = 3
- summon_type = list(/mob/living/simple_animal/hostile/creature)
+ summon_type = list(/mob/living/simple_animal/hostile/netherworld)
cast_sound = 'sound/magic/summonitems_generic.ogg'
/obj/effect/proc_holder/spell/targeted/trigger/blind
@@ -289,7 +289,7 @@
var/mob/living/M = AM
M.Knockdown(stun_amt)
to_chat(M, "
You're thrown back by [user]!")
- AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
+ AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?!
name = "Tail Sweep"
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 9784dd115c..63b955a571 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -18,7 +18,7 @@
return 0
var/obj/item/bodypart/affecting = C.get_bodypart("chest")
- affecting.receive_damage(Clamp(brute_dam/2, 15, 50), Clamp(burn_dam/2, 0, 50)) //Damage the chest based on limb's existing damage
+ affecting.receive_damage(CLAMP(brute_dam/2, 15, 50), CLAMP(burn_dam/2, 0, 50)) //Damage the chest based on limb's existing damage
C.visible_message("
[C]'s [src.name] has been violently dismembered!")
C.emote("scream")
drop_limb()
@@ -102,7 +102,7 @@
for(var/obj/item/I in embedded_objects)
embedded_objects -= I
- I.loc = src
+ I.forceMove(src)
if(!C.has_embedded_objects())
C.clear_alert("embeddedobject")
@@ -142,16 +142,16 @@
//when a limb is dropped, the internal organs are removed from the mob and put into the limb
/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C)
Remove(C)
- loc = LB
+ forceMove(LB)
/obj/item/organ/brain/transfer_to_limb(obj/item/bodypart/head/LB, mob/living/carbon/human/C)
Remove(C) //Changeling brain concerns are now handled in Remove
- loc = LB
+ forceMove(LB)
LB.brain = src
if(brainmob)
LB.brainmob = brainmob
brainmob = null
- LB.brainmob.loc = LB
+ LB.brainmob.forceMove(LB)
LB.brainmob.container = LB
LB.brainmob.stat = DEAD
@@ -167,7 +167,7 @@
..()
if(C && !special)
if(C.handcuffed)
- C.handcuffed.loc = C.loc
+ C.handcuffed.forceMove(C.loc)
C.handcuffed.dropped(C)
C.handcuffed = null
C.update_handcuffed()
@@ -185,7 +185,7 @@
..()
if(C && !special)
if(C.handcuffed)
- C.handcuffed.loc = C.loc
+ C.handcuffed.forceMove(C.loc)
C.handcuffed.dropped(C)
C.handcuffed = null
C.update_handcuffed()
@@ -201,7 +201,7 @@
/obj/item/bodypart/r_leg/drop_limb(special)
if(owner && !special)
if(owner.legcuffed)
- owner.legcuffed.loc = owner.loc
+ owner.legcuffed.forceMove(owner.loc)
owner.legcuffed.dropped(owner)
owner.legcuffed = null
owner.update_inv_legcuffed()
@@ -212,7 +212,7 @@
/obj/item/bodypart/l_leg/drop_limb(special) //copypasta
if(owner && !special)
if(owner.legcuffed)
- owner.legcuffed.loc = owner.loc
+ owner.legcuffed.forceMove(owner.loc)
owner.legcuffed.dropped(owner)
owner.legcuffed = null
owner.update_inv_legcuffed()
@@ -236,6 +236,11 @@
if(pill)
pill.forceMove(src)
+ //Make sure de-zombification happens before organ removal instead of during it
+ var/obj/item/organ/zombie_infection/ooze = owner.getorganslot(ORGAN_SLOT_ZOMBIE)
+ if(istype(ooze))
+ ooze.transfer_to_limb(src, owner)
+
name = "[owner.real_name]'s head"
..()
@@ -265,7 +270,7 @@
attach_limb(C, special)
/obj/item/bodypart/proc/attach_limb(mob/living/carbon/C, special)
- loc = null
+ moveToNullspace()
owner = C
C.bodyparts += src
if(held_index)
@@ -306,7 +311,7 @@
if(brain)
if(brainmob)
brainmob.container = null //Reset brainmob head var.
- brainmob.loc = brain //Throw mob into brain.
+ brainmob.forceMove(brain) //Throw mob into brain.
brain.brainmob = brainmob //Set the brain to use the brainmob
brainmob = null //Set head brainmob var to null
brain.Insert(C) //Now insert the brain proper
diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm
index a4d317ad2a..f631400bee 100644
--- a/code/modules/surgery/bodyparts/head.dm
+++ b/code/modules/surgery/bodyparts/head.dm
@@ -41,10 +41,10 @@
user.visible_message("
[user] saws [src] open and pulls out a brain!", "
You saw [src] open and pull out a brain.")
if(brainmob)
brainmob.container = null
- brainmob.loc = brain
+ brainmob.forceMove(brain)
brain.brainmob = brainmob
brainmob = null
- brain.loc = T
+ brain.forceMove(T)
brain = null
update_icon_dropped()
else
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index e460a8c97f..7ac387b4d8 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -118,7 +118,7 @@
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
L.embedded_objects -= I
- I.loc = T
+ I.forceMove(T)
clear_alert("embeddedobject")
diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm
index f477535dab..dc8b3543fa 100644
--- a/code/modules/surgery/organ_manipulation.dm
+++ b/code/modules/surgery/organ_manipulation.dm
@@ -176,7 +176,7 @@
"
You successfully extract [I] from [target]'s [parse_zone(target_zone)].")
add_logs(user, target, "surgically removed [I.name] from", addition="INTENT: [uppertext(user.a_intent)]")
I.Remove(target)
- I.loc = get_turf(target)
+ I.forceMove(get_turf(target))
else
user.visible_message("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!",
"
You can't extract anything from [target]'s [parse_zone(target_zone)]!")
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index aa1ea10cd0..e23e7ff7d3 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -161,7 +161,6 @@
name = "arm-mounted laser implant"
desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arm and remains inside when not in use."
icon_state = "arm_laser"
- origin_tech = "materials=4;combat=4;biotech=4;powerstorage=4;syndicate=3"
contents = newlist(/obj/item/gun/energy/laser/mounted)
/obj/item/organ/cyberimp/arm/gun/laser/l
@@ -172,7 +171,6 @@
name = "arm-mounted taser implant"
desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arm and remains inside when not in use."
icon_state = "arm_taser"
- origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4"
contents = newlist(/obj/item/gun/energy/e_gun/advtaser/mounted)
/obj/item/organ/cyberimp/arm/gun/taser/l
@@ -182,7 +180,6 @@
/obj/item/organ/cyberimp/arm/toolset
name = "integrated toolset implant"
desc = "A stripped-down version of the engineering cyborg toolset, designed to be installed on subject's arm. Contains all necessary tools."
- origin_tech = "materials=3;engineering=4;biotech=3;powerstorage=4"
contents = newlist(/obj/item/screwdriver/cyborg, /obj/item/wrench/cyborg, /obj/item/weldingtool/largetank/cyborg,
/obj/item/crowbar/cyborg, /obj/item/wirecutters/cyborg, /obj/item/device/multitool/cyborg)
@@ -200,19 +197,17 @@
name = "arm-mounted energy blade"
desc = "An illegal and highly dangerous cybernetic implant that can project a deadly blade of concentrated energy."
contents = newlist(/obj/item/melee/transforming/energy/blade/hardlight)
- origin_tech = "materials=4;combat=5;biotech=3;powerstorage=2;syndicate=5"
/obj/item/organ/cyberimp/arm/medibeam
name = "integrated medical beamgun"
desc = "A cybernetic implant that allows the user to project a healing beam from their hand."
contents = newlist(/obj/item/gun/medbeam)
- origin_tech = "materials=5;combat=2;biotech=5;powerstorage=4;syndicate=1"
+
/obj/item/organ/cyberimp/arm/flash
name = "integrated high-intensity photon projector" //Why not
desc = "An integrated projector mounted onto a user's arm that is able to be used as a powerful flash."
contents = newlist(/obj/item/device/assembly/flash/armimplant)
- origin_tech = "materials=4;combat=3;biotech=4;magnets=4;powerstorage=3"
/obj/item/organ/cyberimp/arm/flash/Initialize()
. = ..()
@@ -224,13 +219,11 @@
name = "arm electrification implant"
desc = "An illegal combat implant that allows the user to administer disabling shocks from their arm."
contents = newlist(/obj/item/borg/stun)
- origin_tech = "materials=3;combat=5;biotech=4;powerstorage=4;syndicate=3"
/obj/item/organ/cyberimp/arm/combat
name = "combat cybernetics implant"
desc = "A powerful cybernetic implant that contains combat modules built into the user's arm."
contents = newlist(/obj/item/melee/transforming/energy/blade/hardlight, /obj/item/gun/medbeam, /obj/item/borg/stun, /obj/item/device/assembly/flash/armimplant)
- origin_tech = "materials=5;combat=7;biotech=5;powerstorage=5;syndicate=6;programming=5"
/obj/item/organ/cyberimp/arm/combat/Initialize()
. = ..()
@@ -242,4 +235,3 @@
name = "surgical toolset implant"
desc = "A set of surgical tools hidden behind a concealed panel on the user's arm."
contents = newlist(/obj/item/retractor/augment, /obj/item/hemostat/augment, /obj/item/cautery/augment, /obj/item/surgicaldrill/augment, /obj/item/scalpel/augment, /obj/item/circular_saw/augment, /obj/item/surgical_drapes)
- origin_tech = "materials=3;engineering=3;biotech=3;programming=2;magnets=3"
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index 1e93c4df4a..a6635ed78d 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -14,7 +14,6 @@
var/synthesizing = 0
var/poison_amount = 5
slot = ORGAN_SLOT_STOMACH
- origin_tech = "materials=2;powerstorage=2;biotech=2"
/obj/item/organ/cyberimp/chest/nutriment/on_life()
if(synthesizing)
@@ -43,14 +42,12 @@
implant_color = "#006607"
hunger_threshold = NUTRITION_LEVEL_HUNGRY
poison_amount = 10
- origin_tech = "materials=4;powerstorage=3;biotech=3"
/obj/item/organ/cyberimp/chest/reviver
name = "Reviver implant"
desc = "This implant will attempt to revive you if you lose consciousness. For the faint of heart!"
icon_state = "chest_implant"
implant_color = "#AD0000"
- origin_tech = "materials=5;programming=4;biotech=4"
slot = ORGAN_SLOT_HEART_AID
var/revive_cost = 0
var/reviving = 0
@@ -122,7 +119,6 @@
Unlike regular jetpack, this device has no stabilization system."
slot = ORGAN_SLOT_THRUSTERS
icon_state = "imp_jetpack"
- origin_tech = "materials=4;magnets=4;biotech=4;engineering=5"
implant_overlay = null
implant_color = null
actions_types = list(/datum/action/item_action/organ_action/toggle)
diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm
index 29fc6f1ac2..37cbb9e022 100644
--- a/code/modules/surgery/organs/augments_eyes.dm
+++ b/code/modules/surgery/organs/augments_eyes.dm
@@ -29,13 +29,11 @@
/obj/item/organ/cyberimp/eyes/hud/medical
name = "Medical HUD implant"
desc = "These cybernetic eye implants will display a medical HUD over everything you see."
- origin_tech = "materials=4;programming=4;biotech=4"
HUD_type = DATA_HUD_MEDICAL_ADVANCED
/obj/item/organ/cyberimp/eyes/hud/security
name = "Security HUD implant"
desc = "These cybernetic eye implants will display a security HUD over everything you see."
- origin_tech = "materials=4;programming=4;biotech=3;combat=3"
HUD_type = DATA_HUD_SECURITY_ADVANCED
/obj/item/organ/cyberimp/eyes/hud/security/syndicate
diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm
index a6c1517faa..7e209a1de0 100644
--- a/code/modules/surgery/organs/augments_internal.dm
+++ b/code/modules/surgery/organs/augments_internal.dm
@@ -45,7 +45,6 @@
var/list/stored_items = list()
implant_color = "#DE7E00"
slot = ORGAN_SLOT_BRAIN_ANTIDROP
- origin_tech = "materials=4;programming=5;biotech=4"
actions_types = list(/datum/action/item_action/organ_action/toggle)
/obj/item/organ/cyberimp/brain/anti_drop/ui_action_click()
@@ -102,7 +101,6 @@
desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned."
implant_color = "#FFFF00"
slot = ORGAN_SLOT_BRAIN_ANTISTUN
- origin_tech = "materials=5;programming=4;biotech=5"
/obj/item/organ/cyberimp/brain/anti_stun/on_life()
..()
@@ -135,7 +133,6 @@
icon_state = "implant_mask"
slot = ORGAN_SLOT_BREATHING_TUBE
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=2;biotech=3"
/obj/item/organ/cyberimp/mouth/breathing_tube/emp_act(severity)
if(prob(60/severity))
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 75d4aa0bcc..f8f57c650f 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -103,7 +103,6 @@
name = "thermal eyes"
desc = "These cybernetic eye implants will give you thermal vision. Vertical slit pupil included."
eye_color = "FC0"
- origin_tech = "materials=5;programming=4;biotech=4;magnets=4;syndicate=1"
sight_flags = SEE_MOBS
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
flash_protect = -1
@@ -141,7 +140,6 @@
/obj/item/organ/eyes/robotic/shield
name = "shielded robotic eyes"
desc = "These reactive micro-shields will protect you from welders and flashes without obscuring your vision."
- origin_tech = "materials=4;biotech=3;engineering=4;plasmatech=3"
flash_protect = 2
/obj/item/organ/eyes/robotic/shield/emp_act(severity)
@@ -152,7 +150,6 @@
/obj/item/organ/eyes/robotic/glow
name = "High Luminosity Eyes"
desc = "Special glowing eyes, used by snowflakes who want to be special."
- origin_tech = "materials=3;biotech=3;engineering=3;magnets=4"
eye_color = "000"
actions_types = list(/datum/action/item_action/organ_action/use, /datum/action/item_action/organ_action/toggle)
var/current_color_string = "#ffffff"
@@ -202,7 +199,7 @@
return
var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num
- set_distance(Clamp(range, 0, max_light_beam_distance))
+ set_distance(CLAMP(range, 0, max_light_beam_distance))
assume_rgb(C)
/obj/item/organ/eyes/robotic/glow/proc/assume_rgb(newcolor)
diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm
index bc85d9c46e..21d15fb609 100644
--- a/code/modules/surgery/organs/heart.dm
+++ b/code/modules/surgery/organs/heart.dm
@@ -4,7 +4,6 @@
icon_state = "heart-on"
zone = "chest"
slot = ORGAN_SLOT_HEART
- origin_tech = "biotech=5"
// Heart attack code is in code/modules/mob/living/carbon/human/life.dm
var/beating = 1
var/icon_base = "heart"
@@ -54,7 +53,7 @@
var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE)
var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE)
var/mob/living/carbon/H = owner
-
+
if(H.health <= HEALTH_THRESHOLD_CRIT && beat != BEAT_SLOW)
beat = BEAT_SLOW
H.playsound_local(get_turf(H), slowbeat,40,0, channel = CHANNEL_HEARTBEAT)
@@ -76,7 +75,6 @@
desc = "A heart that, when inserted, will force you to pump it manually."
icon_state = "cursedheart-off"
icon_base = "cursedheart"
- origin_tech = "biotech=6"
actions_types = list(/datum/action/item_action/organ_action/cursed_heart)
var/last_pump = 0
var/add_colour = TRUE //So we're not constantly recreating colour datums
@@ -151,7 +149,6 @@
name = "cybernetic heart"
desc = "An electronic device designed to mimic the functions of an organic human heart. Offers no benefit over an organic heart other than being easy to make."
icon_state = "heart-c"
- origin_tech = "biotech=5"
/obj/item/organ/heart/cybernetic/emp_act()
Stop()
diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm
index 352958d9b8..d2de50ce3e 100755
--- a/code/modules/surgery/organs/liver.dm
+++ b/code/modules/surgery/organs/liver.dm
@@ -5,7 +5,6 @@
/obj/item/organ/liver
name = "liver"
icon_state = "liver"
- origin_tech = "biotech=3"
w_class = WEIGHT_CLASS_NORMAL
zone = "chest"
slot = ORGAN_SLOT_LIVER
@@ -68,13 +67,11 @@
name = "cybernetic liver"
icon_state = "liver-c"
desc = "An electronic device designed to mimic the functions of a human liver. It has no benefits over an organic liver, but is easy to produce."
- origin_tech = "biotech=4"
/obj/item/organ/liver/cybernetic/upgraded
name = "upgraded cybernetic liver"
icon_state = "liver-c-u"
desc = "An upgraded version of the cybernetic liver, designed to improve upon organic livers. It is resistant to alcohol poisoning and is very robust at filtering toxins."
- origin_tech = "biotech=6"
alcohol_tolerance = 0.001
maxHealth = 200 //double the health of a normal liver
toxTolerance = 15 //can shrug off up to 15u of toxins
diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm
index a7ea63f101..102ac9720f 100644
--- a/code/modules/surgery/organs/lungs.dm
+++ b/code/modules/surgery/organs/lungs.dm
@@ -111,7 +111,7 @@
if(safe_oxygen_max)
if(O2_pp > safe_oxygen_max)
var/ratio = (breath_gases[/datum/gas/oxygen][MOLES]/safe_oxygen_max) * 10
- H.apply_damage_type(Clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type)
+ H.apply_damage_type(CLAMP(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type)
H.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy)
else
H.clear_alert("too_much_oxy")
@@ -139,7 +139,7 @@
if(safe_nitro_max)
if(N2_pp > safe_nitro_max)
var/ratio = (breath_gases[/datum/gas/nitrogen][MOLES]/safe_nitro_max) * 10
- H.apply_damage_type(Clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type)
+ H.apply_damage_type(CLAMP(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type)
H.throw_alert("too_much_nitro", /obj/screen/alert/too_much_nitro)
else
H.clear_alert("too_much_nitro")
@@ -205,7 +205,7 @@
if(safe_toxins_max)
if(Toxins_pp > safe_toxins_max)
var/ratio = (breath_gases[/datum/gas/plasma][MOLES]/safe_toxins_max) * 10
- H.apply_damage_type(Clamp(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type)
+ H.apply_damage_type(CLAMP(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type)
H.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
else
H.clear_alert("too_much_tox")
@@ -356,7 +356,6 @@
name = "cybernetic lungs"
desc = "A cybernetic version of the lungs found in traditional humanoid entities. It functions the same as an organic lung and is merely meant as a replacement."
icon_state = "lungs-c"
- origin_tech = "biotech=4"
/obj/item/organ/lungs/cybernetic/emp_act()
owner.losebreath = 20
@@ -366,8 +365,6 @@
name = "upgraded cybernetic lungs"
desc = "A more advanced version of the stock cybernetic lungs. They are capable of filtering out lower levels of toxins and carbon dioxide."
icon_state = "lungs-c-u"
- origin_tech = "biotech=5"
-
safe_toxins_max = 20
safe_co2_max = 20
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index 4097f3fb47..a384845281 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -3,7 +3,6 @@
icon = 'icons/obj/surgery.dmi'
var/mob/living/carbon/owner = null
var/status = ORGAN_ORGANIC
- origin_tech = "biotech=3"
w_class = WEIGHT_CLASS_SMALL
throwforce = 0
var/zone = "chest"
@@ -29,7 +28,7 @@
owner = M
M.internal_organs |= src
M.internal_organs_slot[slot] = src
- loc = null
+ moveToNullspace()
for(var/X in actions)
var/datum/action/A = X
A.Grant(M)
@@ -66,7 +65,6 @@
S.desc = desc
S.icon = icon
S.icon_state = icon_state
- S.origin_tech = origin_tech
S.w_class = w_class
return S
diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm
index 2bf34334f4..1422c20c7b 100755
--- a/code/modules/surgery/organs/stomach.dm
+++ b/code/modules/surgery/organs/stomach.dm
@@ -1,7 +1,6 @@
/obj/item/organ/stomach
name = "stomach"
icon_state = "stomach"
- origin_tech = "biotech=4"
w_class = WEIGHT_CLASS_NORMAL
zone = "chest"
slot = ORGAN_SLOT_STOMACH
diff --git a/code/modules/surgery/remove_embedded_object.dm b/code/modules/surgery/remove_embedded_object.dm
index e116c23303..577541e6c4 100644
--- a/code/modules/surgery/remove_embedded_object.dm
+++ b/code/modules/surgery/remove_embedded_object.dm
@@ -26,7 +26,7 @@
var/objects = 0
for(var/obj/item/I in L.embedded_objects)
objects++
- I.loc = get_turf(H)
+ I.forceMove(get_turf(H))
L.embedded_objects -= I
if(!H.has_embedded_objects())
H.clear_alert("embeddedobject")
@@ -39,4 +39,4 @@
else
to_chat(user, "
You can't find [target]'s [parse_zone(user.zone_selected)], let alone any objects embedded in it!")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm
index 084ed3f81d..310513326a 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -6,7 +6,6 @@
materials = list(MAT_METAL=6000, MAT_GLASS=3000)
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=1;biotech=1"
/obj/item/retractor/augment
@@ -17,7 +16,6 @@
materials = list(MAT_METAL=6000, MAT_GLASS=3000)
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=1;biotech=1"
toolspeed = 0.5
@@ -29,7 +27,6 @@
materials = list(MAT_METAL=5000, MAT_GLASS=2500)
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "pinched")
@@ -41,7 +38,6 @@
materials = list(MAT_METAL=5000, MAT_GLASS=2500)
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=1;biotech=1"
toolspeed = 0.5
attack_verb = list("attacked", "pinched")
@@ -54,7 +50,6 @@
materials = list(MAT_METAL=2500, MAT_GLASS=750)
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=1;biotech=1"
attack_verb = list("burnt")
@@ -66,7 +61,6 @@
materials = list(MAT_METAL=2500, MAT_GLASS=750)
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_TINY
- origin_tech = "materials=1;biotech=1"
toolspeed = 0.5
attack_verb = list("burnt")
@@ -83,7 +77,6 @@
flags_1 = CONDUCT_1
force = 15
w_class = WEIGHT_CLASS_NORMAL
- origin_tech = "materials=1;biotech=1"
attack_verb = list("drilled")
@@ -97,7 +90,6 @@
flags_1 = CONDUCT_1
force = 10
w_class = WEIGHT_CLASS_SMALL
- origin_tech = "materials=1;biotech=1"
toolspeed = 0.5
attack_verb = list("drilled")
@@ -116,7 +108,6 @@
throw_speed = 3
throw_range = 5
materials = list(MAT_METAL=4000, MAT_GLASS=1000)
- origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP_ACCURATE
@@ -133,7 +124,6 @@
throw_speed = 3
throw_range = 5
materials = list(MAT_METAL=4000, MAT_GLASS=1000)
- origin_tech = "materials=1;biotech=1"
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
toolspeed = 0.5
hitsound = 'sound/weapons/bladeslice.ogg'
@@ -160,7 +150,6 @@
throw_speed = 2
throw_range = 5
materials = list(MAT_METAL=10000, MAT_GLASS=6000)
- origin_tech = "biotech=1;combat=1"
attack_verb = list("attacked", "slashed", "sawed", "cut")
sharpness = IS_SHARP
@@ -178,7 +167,6 @@
throw_speed = 2
throw_range = 5
materials = list(MAT_METAL=10000, MAT_GLASS=6000)
- origin_tech = "biotech=1;combat=1"
toolspeed = 0.5
attack_verb = list("attacked", "slashed", "sawed", "cut")
sharpness = IS_SHARP
@@ -189,7 +177,6 @@
icon = 'icons/obj/surgery.dmi'
icon_state = "surgical_drapes"
w_class = WEIGHT_CLASS_TINY
- origin_tech = "biotech=1"
attack_verb = list("slapped")
/obj/item/surgical_drapes/attack(mob/living/M, mob/user)
@@ -225,7 +212,7 @@
add_overlay(img)
add_overlay("evidence")
desc = "An organ storage container holding [I]."
- I.loc = src
+ I.forceMove(src)
w_class = I.w_class
/obj/item/organ_storage/attack_self(mob/user)
diff --git a/code/modules/telesci/telepad.dm b/code/modules/telesci/telepad.dm
index 32a2acf9c6..d712b773d3 100644
--- a/code/modules/telesci/telepad.dm
+++ b/code/modules/telesci/telepad.dm
@@ -18,7 +18,6 @@
/obj/item/circuitboard/machine/telesci_pad
name = "Telepad (Machine Board)"
build_path = /obj/machinery/telepad
- origin_tech = "programming=4;engineering=3;plasmatech=4;bluespace=4"
req_components = list(
/obj/item/ore/bluespace_crystal = 2,
/obj/item/stock_parts/capacitor = 1,
@@ -104,7 +103,6 @@
icon = 'icons/obj/radio.dmi'
icon_state = "beacon"
item_state = "beacon"
- origin_tech = "bluespace=3"
/obj/item/device/telepad_beacon/attack_self(mob/user)
if(user)
diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm
index 42d863d968..3925b863ff 100644
--- a/code/modules/vehicles/pimpin_ride.dm
+++ b/code/modules/vehicles/pimpin_ride.dm
@@ -24,7 +24,6 @@
desc = "An upgrade for mobile janicarts."
icon = 'icons/obj/vehicles.dmi'
icon_state = "upgrade"
- origin_tech = "materials=3;engineering=4"
/obj/vehicle/ridden/janicart/examine(mob/user)
..()
diff --git a/code/modules/vore/resizing/sizegun_vr.dm b/code/modules/vore/resizing/sizegun_vr.dm
index de6e0eb7f0..51b6e24736 100644
--- a/code/modules/vore/resizing/sizegun_vr.dm
+++ b/code/modules/vore/resizing/sizegun_vr.dm
@@ -11,7 +11,6 @@
fire_sound = 'sound/weapons/wave.ogg'
charge_cost = 100
projectile_type = /obj/item/projectile/beam/shrinklaser
- origin_tech = "redspace=1;bluespace=4"
modifystate = "sizegun-shrink"
selfcharge = 1
firemodes = list(
@@ -88,7 +87,6 @@ datum/design/sizeray
name = "Size Ray"
desc = "Abuse bluespace tech to alter living matter scale."
id = "sizeray"
- req_tech = list("combat" = 5, "materials" = 4, "engineering" = 5, "bluespace" = 4)
build_type = PROTOLATHE
materials = list(MAT_METAL = 1000, MAT_GLASS = 1000, MAT_DIAMOND = 2500, MAT_URANIUM = 2500, MAT_TITANIUM = 1000)
build_path = /obj/item/gun/energy/laser/sizeray
@@ -155,7 +153,6 @@ datum/design/sizeray
desc = "Size manipulator using bluespace breakthroughs."
item_state = null //so the human update icon uses the icon_state instead.
ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray, /obj/item/ammo_casing/energy/laser/growthray)
- origin_tech = "combat=1;magnets=2"
selfcharge = 1
charge_delay = 5
ammo_x_offset = 2
diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm
index d55059960f..07e3648417 100644
--- a/code/modules/zombie/organs.dm
+++ b/code/modules/zombie/organs.dm
@@ -4,7 +4,6 @@
zone = "head"
slot = ORGAN_SLOT_ZOMBIE
icon_state = "blacktumor"
- origin_tech = "biotech=5"
var/datum/species/old_species = /datum/species/human
var/living_transformation_time = 30
var/converts_living = FALSE
diff --git a/config/admin_ranks.txt b/config/admin_ranks.txt
index 96737c5484..3cf5cbfb72 100644
--- a/config/admin_ranks.txt
+++ b/config/admin_ranks.txt
@@ -27,17 +27,19 @@
# +RIGHTS (or +PERMISSIONS) = allows you to promote and/or demote people.
# +SOUND (or +SOUNDS) = allows you to upload and play sounds
# +SPAWN (or +CREATE) = mob transformations, spawning of most atoms including mobs (high-risk atoms, e.g. blackholes, will require the +FUN flag too)
+# +AUTOLOGIN = admin gains powers upon connect. This defaults to on, you can use -AUTOLOGIN to make a role require using the readmin verb to gain powers. (this does not effect the admin's ability to walk past bans or other on-connect limitations like panic bunker or pop limit.)
# +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag
# END_KEYWORDS
-Admin Observer
+Admin Observer = -AUTOLOGIN
Moderator = +ADMIN
Admin Candidate = +@
Trial Admin = +@ +SPAWN +REJUV +VAREDIT +BAN
Badmin = +@ +POSSESS +BUILDMODE +SERVER +FUN
Game Admin = +@ +STEALTH +SOUNDS +DEBUG
Game Master = +EVERYTHING
+Lazy Master = +EVERYTHING -AUTOLOGIN
Host = +EVERYTHING
-Coder = +DEBUG +VAREDIT +SERVER +SPAWN
\ No newline at end of file
+Coder = +DEBUG +VAREDIT +SERVER +SPAWN -AUTOLOGIN
diff --git a/config/admins.txt b/config/admins.txt
index b7d8cf0e6b..0f5684b465 100644
--- a/config/admins.txt
+++ b/config/admins.txt
@@ -15,7 +15,7 @@ Optimumtact = Host
NewSta = Game Master
Expletives = Game Master
kingofkosmos = Game Master
-MrStonedOne = Game Master
+MrStonedOne = Lazy Master
microscopics = Game Master
Gun Hog = Game Master
KorPhaeron = Game Master
diff --git a/config/config.txt b/config/config.txt
index fb648a5fa9..e43b38b568 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -1,3 +1,9 @@
+# You can use the "$include" directive to split your configs however you want
+
+$include game_options.txt
+$include dbconfig.txt
+$include comms.txt
+
# You can use the @ character at the beginning of a config option to lock it from being edited in-game
# Example usage:
# @SERVERNAME tgstation
diff --git a/html/changelog.html b/html/changelog.html
index 45dfe57b20..d73ebdcd62 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -1279,3 +1279,1492 @@