Techwebs & Experi-Sci (#17987)

* Techwebs

* Add basic stock parts

* Techweb production machines

* Circuit Imprinter

* More work

* More designs

* More designs, nodes'

* More more

* Better sorting for designs

* Add the exosuit fab'

* More conversions

* More and more and more

* mechfab parts

* Modsuit Designs

* Pinnace baron

* Equipment

* more mechfab

* vehicles

* more mecha

* Micro mechs

* Update mechfab_designs.dm

* no time

* zero

* Update mechfab_designs.dm

* Prosthetics Fabricator and fixes

* Update maps to use new parts

* Whoops, fix a few maps

* Fix lint error

* Port scene tools

* Fireworks~~

* Don't label the sex toys as sex toys

* Fixup maps in TGM format

26517b7122: maps/virgo_minitest/virgo_minitest-1.dmm

Automatically commited by: tools\mapmerge2\fixup.py

* Significant portion of designs converted

* Fix paths

* Fix tgui lints

* Just a whole bunch of designs

* Almost doneeee

* ALL DESIGNS CONVERTED

* Merk all of the old stuff

* Fix a few errors

* Fix more errors

* MORE FIX

* Make server control work

* Undo changes to archive

* Fix a TODO

* Make disks work

* Start the long process of finishing the node tree

* One more oops

* All mechfab designs

* Add departmental protolathes

* Down to 200 designs unsorted

* FINISH TECHWEBS

* Fuck whoops

* Remove the debug verbs

* Little map tweaks

* Fix mousedrop

* More map fixes

* Upstream bug lmao

* guess CI hates this

* Fixup maps in TGM format

fe062e7bc4: maps/tether/tether-03-surface3.dmm

Automatically commited by: tools\mapmerge2\fixup.py

* I gotta stop committing this

* Change scree requested

* Make science able to print implants too

* Fix ghost spawns

* Move NSFW gun

* Merk partbundles, make janus module work

* Pretty animation when you complete the tree :)

* Don't display designs you can't print

* Move security protolathes to warden's office

* Make servers recover from power failure gracefully

* Make fabricators drop their mats on the ground when destroyed

* Ore Silo

* Make CI happy

* Fixup maps in TGM format

fe062e7bc4: maps/tether/tether-05-station1.dmm

Automatically commited by: tools\mapmerge2\fixup.py

* Fix MC crash

* Make experiscanner work for borgs

* I REALLY gotta stop committing this

* Make scientists and the RD spawn with an experiscanner

* Lock NIFs behind scanning mice

* Make Biome happy

* Allow scanning Cocoa and Kendrick in case they can't find mice

* Change from Kendrick to Ratthew, ;help maint, or Brick

* Change the name of the /rat/pet class so the experiscanner is more helpful

* Add departmental_flags to a bunch of things

* Remove a few things from security's techfab

* Add a second engineering lathe to atmos

* Fix runtime recycling rig modules, add name to cost sequence

* Add a discount experiment for scanning slime cores

* Change some fluff and shuffle chameleon clothes to bluespace yadayada

* Make closets alt click immune

* Do a bunch of sorting

* Silly

* Hopefully fix all infinite material bugs in techwebs

* bad merge

* quick ai fix

* fix some robot stuff

* axe downlaod fully

* list

* no ref

* easier readable

---------

Co-authored-by: C.L. <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
ShadowLarkens
2025-07-25 21:30:08 -07:00
committed by GitHub
parent 93efaa653a
commit b60cd47309
271 changed files with 19410 additions and 11158 deletions
@@ -98,7 +98,7 @@
if(cell)
user.show_message("\t Power Cell Details: [span_blue("[capitalize(cell.name)]")] with a capacity of [cell.maxcharge] at [round(cell.percent())]% charge")
var/show_title = TRUE
for(var/datum/design/item/prosfab/robot_upgrade/utility/upgrade)
for(var/datum/design_techweb/prosfab/robot_upgrade/utility/upgrade in SSresearch.techweb_designs)
var/obj/item/borg/upgrade/utility/upgrade_type = initial(upgrade.build_path)
var/needs_module = initial(upgrade_type.require_module)
if((!R.module && needs_module) || !initial(upgrade.name) || (R.stat != DEAD && (upgrade_type == /obj/item/borg/upgrade/utility/restart)) || (isshell(R) && (upgrade_type == /obj/item/borg/upgrade/utility/rename)))
@@ -112,7 +112,7 @@
else
user.show_message(span_blue("\t\t [capitalize(initial(upgrade.name))]: [span_green("Usable")]"))
show_title = TRUE
for(var/datum/design/item/prosfab/robot_upgrade/basic/upgrade)
for(var/datum/design_techweb/prosfab/robot_upgrade/basic/upgrade in SSresearch.techweb_designs)
var/obj/item/borg/upgrade/basic/upgrade_type = initial(upgrade.build_path)
var/needs_module = initial(upgrade_type.require_module)
if((!R.module && needs_module) || !initial(upgrade.name) || R.stat == DEAD)
@@ -125,7 +125,7 @@
else
user.show_message(span_blue("\t\t [capitalize(initial(upgrade.name))]: [R.has_basic_upgrade(initial(upgrade.build_path)) ? span_green("Installed") : span_red("Missing")]"))
show_title = TRUE
for(var/datum/design/item/prosfab/robot_upgrade/advanced/upgrade)
for(var/datum/design_techweb/prosfab/robot_upgrade/advanced/upgrade in SSresearch.techweb_designs)
var/obj/item/borg/upgrade/advanced/upgrade_type = initial(upgrade.build_path)
var/needs_module = initial(upgrade_type.require_module)
if((!R.module && needs_module) || !initial(upgrade.name) || R.stat == DEAD)
@@ -138,7 +138,7 @@
else
user.show_message(span_blue("\t\t [capitalize(initial(upgrade.name))]: [R.has_advanced_upgrade(initial(upgrade.build_path)) ? span_green("Installed") : span_red("Missing")]"))
show_title = TRUE
for(var/datum/design/item/prosfab/robot_upgrade/restricted/upgrade)
for(var/datum/design_techweb/prosfab/robot_upgrade/restricted/upgrade in SSresearch.techweb_designs)
var/obj/item/borg/upgrade/restricted/upgrade_type = initial(upgrade.build_path)
var/needs_module = initial(upgrade_type.require_module)
if((!R.module && needs_module) || !initial(upgrade.name) || !R.supports_upgrade(initial(upgrade.build_path)) || R.stat == DEAD)
@@ -151,20 +151,6 @@
else
user.show_message(span_blue("\t\t [capitalize(initial(upgrade.name))]: [R.has_restricted_upgrade(initial(upgrade.build_path)) ? span_green("Installed") : span_red("Missing")]"))
show_title = TRUE
for(var/datum/design/item/prosfab/robot_upgrade/no_prod/upgrade)
var/obj/item/borg/upgrade/no_prod/upgrade_type = initial(upgrade.build_path)
var/needs_module = initial(upgrade_type.require_module)
var/hidden = initial(upgrade_type.hidden_from_scan)
if((!R.module && needs_module) || !initial(upgrade.name) || hidden || R.stat == DEAD)
continue
if(show_title)
user.show_message("\t Special Modules, used for recreation purposes:")
show_title = FALSE
if(R.has_no_prod_upgrade(initial(upgrade.build_path)) == "")
user.show_message(span_blue("\t\t [capitalize(initial(upgrade.name))]: [span_red(span_bold("ERROR"))]"))
else
user.show_message(span_blue("\t\t [capitalize(initial(upgrade.name))]: [R.has_no_prod_upgrade(initial(upgrade.build_path)) ? span_green("Installed") : span_red("Missing")]"))
if("prosthetics")
var/mob/living/carbon/human/H = M
@@ -27,7 +27,6 @@
var/list/deliveryslot_1 = list()
var/list/deliveryslot_2 = list()
var/list/deliveryslot_3 = list()
var/datum/research/techonly/files //Analyzerbelly var.
var/synced = FALSE
var/startdrain = 500
var/max_item_count = 1
@@ -47,7 +46,6 @@
/obj/item/dogborg/sleeper/Initialize(mapload)
. = ..()
files = new /datum/research/techonly(src)
med_analyzer = new /obj/item/healthanalyzer
/obj/item/dogborg/sleeper/Destroy()
@@ -92,12 +90,6 @@
target.forceMove(src)
user.visible_message(span_warning("[hound.name]'s [src.name] groans lightly as [target.name] slips inside."), span_notice("Your [src.name] groans lightly as [target] slips inside."))
playsound(src, gulpsound, vol = 60, vary = 1, falloff = 0.1, preference = /datum/preference/toggle/eating_noises)
if(analyzer && istype(target,/obj/item))
var/obj/item/tech_item = target
var/list/tech_levels = list()
for(var/T in tech_item.origin_tech)
tech_levels += "\The [tech_item] has level [tech_item.origin_tech[T]] in [CallTechName(T)]."
to_chat(user, span_notice("[jointext(tech_levels, "<br>")]"))
if(delivery)
if(islist(deliverylists[delivery_tag]))
deliverylists[delivery_tag] |= target
@@ -295,9 +287,6 @@
dat += span_red("Cargo compartment slot: Fuel.") + "<BR>"
dat += span_red("([jointext(contents - (deliveryslot_1 + deliveryslot_2 + deliveryslot_3),", ")])") + "<BR><BR>"
if(analyzer && !synced)
dat += "<A href='byond://?src=\ref[src];sync=1'>Sync Files</A><BR>"
//Cleaning and there are still un-preserved items
if(cleaning && length(contents - items_preserved))
dat += span_red(span_bold("Self-cleaning mode.") + " [length(contents - items_preserved)] object(s) remaining.") + "<BR>"
@@ -429,25 +418,6 @@
deliverylists[delivery_tag].Cut()
sleeperUI(usr)
return
if(href_list["sync"])
synced = TRUE
var/success = 0
for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
for(var/datum/tech/T in files.known_tech) //Uploading
S.files.AddTech2Known(T)
for(var/datum/tech/T in S.files.known_tech) //Downloading
files.AddTech2Known(T)
success = 1
files.RefreshResearch()
if(success)
to_chat(usr, "You connect to the research server, push your data upstream to it, then pull the resulting merged data from the master branch.")
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
else
to_chat(usr, "Reserch server ping response timed out. Unable to connect. Please contact the system administrator.")
playsound(src, 'sound/machines/buzz-two.ogg', 50, 1)
sleeperUI(usr)
return
if(patient && !(patient.stat & DEAD)) //What is bitwise NOT? ... Thought it was tilde.
if(href_list["inject"] == REAGENT_ID_INAPROVALINE || patient.health > min_health)
inject_chem(usr, href_list["inject"])
@@ -650,11 +620,6 @@
if(!digested)
items_preserved |= T
else
if(analyzer && digested)
var/obj/item/tech_item = T
for(var/tech in tech_item.origin_tech)
files.UpdateTech(tech, tech_item.origin_tech[tech])
synced = FALSE
if(recycles && T.matter)
for(var/material in T.matter)
var/total_material = T.matter[material]
@@ -1,132 +1,3 @@
//A portable analyzer, for research borgs. This is better then giving them a gripper which can hold anything and letting them use the normal analyzer.
/obj/item/portable_destructive_analyzer
name = "Portable Destructive Analyzer"
icon = 'icons/obj/items.dmi'
icon_state = "portable_analyzer"
desc = "Similar to the stationary version, this rather unwieldy device allows you to break down objects in the name of science."
var/min_reliability = 90 //Can't upgrade, call it laziness or a drawback
var/datum/research/techonly/files //The device uses the same datum structure as the R&D computer/server.
//This analyzer can only store tech levels, however.
var/obj/item/loaded_item //What is currently inside the analyzer.
/obj/item/portable_destructive_analyzer/Initialize(mapload)
. = ..()
files = new /datum/research/techonly(src) //Setup the research data holder.
/obj/item/portable_destructive_analyzer/Destroy()
qdel_null(files)
. = ..()
/obj/item/portable_destructive_analyzer/attack_self(user as mob)
var/response = tgui_alert(user, "Analyzing the item inside will *DESTROY* the item for good.\n\
Syncing to the research server will send the data that is stored inside to research.\n\
Ejecting will place the loaded item onto the floor.",
"What would you like to do?", list("Analyze", "Sync", "Eject"))
if(response == "Analyze")
if(loaded_item)
var/confirm = tgui_alert(user, "This will destroy the item inside forever. Are you sure?","Confirm Analyze",list("Yes","No"))
if(confirm == "Yes" && !QDELETED(loaded_item)) //This is pretty copypasta-y
to_chat(user, span_filter_notice("You activate the analyzer's microlaser, analyzing \the [loaded_item] and breaking it down."))
flick("portable_analyzer_scan", src)
playsound(src, 'sound/items/Welder2.ogg', 50, 1)
var/research_levels = list()
for(var/T in loaded_item.origin_tech)
files.UpdateTech(T, loaded_item.origin_tech[T])
research_levels += "\The [loaded_item] had level [loaded_item.origin_tech[T]] in [CallTechName(T)]."
if (length(research_levels))
to_chat(user, span_filter_notice("[jointext(research_levels,"<br>")]"))
loaded_item = null
for(var/obj/I in contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material))//Only deconstructs one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
loaded_item = S
else
qdel(S)
desc = initial(desc)
icon_state = initial(icon_state)
else
qdel(I)
desc = initial(desc)
icon_state = initial(icon_state)
else
return
else
to_chat(user, span_filter_notice("The [src] is empty. Put something inside it first."))
if(response == "Sync")
var/success = 0
for(var/obj/machinery/r_n_d/server/S in GLOB.machines)
for(var/datum/tech/T in files.known_tech) //Uploading
S.files.AddTech2Known(T)
for(var/datum/tech/T in S.files.known_tech) //Downloading
files.AddTech2Known(T)
success = 1
files.RefreshResearch()
if(success)
to_chat(user, span_filter_notice("You connect to the research server, push your data upstream to it, then pull the resulting merged data from the master branch."))
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
else
to_chat(user, span_filter_notice("Reserch server ping response timed out. Unable to connect. Please contact the system administrator."))
playsound(src, 'sound/machines/buzz-two.ogg', 50, 1)
if(response == "Eject")
if(loaded_item)
loaded_item.loc = get_turf(src)
desc = initial(desc)
icon_state = initial(icon_state)
loaded_item = null
else
to_chat(user, span_filter_notice("The [src] is already empty."))
/obj/item/portable_destructive_analyzer/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target)
return
if(!proximity)
return
if(!isturf(target.loc)) // Don't load up stuff if it's inside a container or mob!
return
if(istype(target,/obj/item))
if(loaded_item)
to_chat(user, span_filter_notice("Your [src] already has something inside. Analyze or eject it first."))
return
var/obj/item/I = target
I.loc = src
loaded_item = I
for(var/mob/M in viewers())
M.show_message(span_notice("[user] adds the [I] to the [src]."), 1)
desc = initial(desc) + "<br>It is holding \the [loaded_item]."
flick("portable_analyzer_load", src)
icon_state = "portable_analyzer_full"
/obj/item/portable_scanner
name = "Portable Resonant Analyzer"
icon = 'icons/obj/items.dmi'
icon_state = "portable_scanner"
desc = "An advanced scanning device used for analyzing objects without completely annihilating them for science. Unfortunately, it has no connection to any database like its angrier cousin."
/obj/item/portable_scanner/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target)
return
if(!proximity)
return
if(istype(target,/obj/item))
var/obj/item/I = target
if(do_after(src, 5 SECONDS * I.w_class))
for(var/mob/M in viewers())
M.show_message(span_notice("[user] sweeps \the [src] over \the [I]."), 1)
flick("[initial(icon_state)]-scan", src)
if(I.origin_tech && I.origin_tech.len)
for(var/T in I.origin_tech)
to_chat(user, span_notice("\The [I] had level [I.origin_tech[T]] in [CallTechName(T)]."))
else
to_chat(user, span_notice("\The [I] cannot be scanned by \the [src]."))
//This is used to unlock other borg covers.
/obj/item/card/robot //This is not a child of id cards, as to avoid dumb typechecks on computers.
name = "access code transmission device"
@@ -663,7 +663,7 @@
/obj/item/robot_module/robot/research/create_equipment(var/mob/living/silicon/robot/robot)
..()
src.modules += new /obj/item/portable_destructive_analyzer(src)
src.modules += new /obj/item/experi_scanner(src)
src.modules += new /obj/item/robotanalyzer(src)
src.modules += new /obj/item/card/robot(src)
src.modules += new /obj/item/gripper/research(src)
@@ -475,4 +475,5 @@
rest_sprite_options = list("Default", "Sit", "Bellyup")
/datum/robot_sprite/dogborg/crisis/smolraptor/alt
name = "Small Raptor Alt"
sprite_icon_state = "smolraptor_alt"
@@ -248,7 +248,7 @@
minbodytemp = 0
/mob/living/simple_mob/vore/aggressive/rat/pet
name = "pet rat"
name = "Giant Rat Siblings"
ai_holder_type = /datum/ai_holder/simple_mob/retaliate
/mob/living/simple_mob/vore/aggressive/rat/pet/Initialize(mapload)