From aa820c08fe0467cd0af9c9bc8f83f292fd6f4467 Mon Sep 17 00:00:00 2001
From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Date: Thu, 7 Sep 2023 16:59:17 +0000
Subject: [PATCH] Oldstation now has their own RND (#78132)
## About The Pull Request
This PR does many things and I expect to be asked to atomize some stuff.
### Oldstation Additions
Oldstation now has their own research server, generating their own
points. To help alleviate major concerns, they have a few stuff to help
with this:
- They now have a pre-built operating computer
- They now have an Autopsy scanner
- They now have access to Experimental Dissection
Experimental Dissection is the old dissection, giving research points in
the form of paper notes on completion. They must be turned in to the RND
server (only works on the Oldstation one, so you can't abuse this) for
points. This was an idea I've had for some time, as Oldstation is used
somewhat as a representation of how ss13 used to be (through its use of
directional windows (before they got removed, but I'd like to bring them
back), old IDs, RTGs, and old engines before they got removed from the
game fully)
Considering there are 11 alien mobs in Oldstation, there is 27.5k
research points to get from alien corpses, enough to bring them up to
speed with whatever they wish to do. This is their 'alternative' for
experiments (which they can still do if they want, but it is very hard
to do, outside of dissection which is needed for the node).
This surgery isn't repeatable, isn't upgradable, and isn't removed by
being healed. It is not mutually exclusive with autopsy (so you can't
ruin yourself doing the wrong surgery).
### Other stuff
- Ninjas now drain RND points from the server they drain from, rather
than always hitting science
- Syncing machines to research roundstart is now a macro, and now
immediately syncs to a server on your Z-level. Machines will
automatically connect to the Science servers if none else are available.
### non-player facing
- Science, Admin, and Oldstation techwebs are now no longer vars on
research, but stored in research's list of techwebs.
- ``get_available_servers`` and ``find_valid_servers`` are now procs on
the research subsystem, rather than the experisci component.
- Oldstation code has been split into separate files.
## Why It's Good For The Game
Oldstation is one of my favorite ruins, but it is also one of the
largest complaints for RND (along with Golems) because they use the
station's Science nodes & points (I recently tried de-hardcoding Science
stuff to help prepare for this, but I didn't get everything in advance).
The complaint stems from these ghost roles, who are meant to be a fun
activity to do while waiting for the next round, using the station's
research points for their own stuff, completely untrackable unless
someone goes out of their way to grief a ghost spawn just for using
points to get things they need. These roles make their own servers to
drain the station, and I find that unfun and quite boring for everyone-
it's also not very flavorful, why would Charliestation know of the
station's RND to take advantage of it?
This hopes to fix those issues, make Charliestation more worthwhile, and
more flavorful.
## Changelog
:cl:
fix: Getting a node researched now properly makes it no longer hidden.
fix: Ninjas draining RD servers now drains it from the connected
techweb, rather than sniping Science.
balance: Machines will first try to connect to a techweb with servers on
their z-level, with the Science techweb remaining as fallback.
add: Oldstation RND, comes with their own Techweb and special surgery to
gain research points through dissecting Xenomorphs.
/:cl:
---
_maps/RandomRuins/SpaceRuins/oldstation.dmm | 25 ++-
code/__DEFINES/research.dm | 14 ++
code/controllers/subsystem/research.dm | 38 ++++-
code/game/machinery/computer/_computer.dm | 1 -
code/game/machinery/computer/dna_console.dm | 5 +-
.../machinery/computer/operating_computer.dm | 4 +-
.../machines/machine_circuitboards.dm | 7 +-
.../antagonists/ninja/ninjaDrainAct.dm | 2 +-
.../pirate/pirate_shuttle_equipment.dm | 3 +-
.../experiment/handlers/experiment_handler.dm | 33 +---
.../oldstation/oldstation_cytology.dm | 29 ++++
.../oldstation_fluff.dm} | 156 ------------------
.../oldstation/oldstation_machines.dm | 8 +
.../oldstation/oldstation_mod.dm | 116 +++++++++++++
.../oldstation/oldstation_rnd.dm | 29 ++++
.../mob/living/simple_animal/bot/medbot.dm | 8 +-
.../file_system/programs/frontier.dm | 2 +-
.../file_system/programs/techweb.dm | 4 +-
.../research/designs/medical_designs.dm | 7 +
code/modules/research/experimentor.dm | 7 +-
.../modules/research/machinery/_production.dm | 6 +-
code/modules/research/rdconsole.dm | 6 +-
code/modules/research/rdmachines.dm | 16 +-
code/modules/research/research_disk.dm | 2 +-
code/modules/research/server.dm | 10 +-
code/modules/research/server_control.dm | 4 +-
code/modules/research/techweb/_techweb.dm | 3 +-
.../modules/research/techweb/_techweb_node.dm | 7 +-
code/modules/research/techweb/all_nodes.dm | 14 +-
.../modules/research/techweb/techweb_types.dm | 14 +-
code/modules/surgery/autopsy.dm | 2 +-
.../surgery/experimental_dissection.dm | 152 +++++++++++++++++
.../modules/vehicles/mecha/mech_fabricator.dm | 17 +-
.../modules/wiremod/core/component_printer.dm | 14 +-
tgstation.dme | 7 +-
35 files changed, 517 insertions(+), 255 deletions(-)
create mode 100644 code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_cytology.dm
rename code/modules/mapfluff/ruins/spaceruin_code/{oldstation.dm => oldstation/oldstation_fluff.dm} (64%)
create mode 100644 code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_machines.dm
create mode 100644 code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm
create mode 100644 code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_rnd.dm
create mode 100644 code/modules/surgery/experimental_dissection.dm
diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
index 25b8ce68763..e134100000d 100644
--- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm
+++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
@@ -1284,6 +1284,7 @@
pixel_x = 3;
pixel_y = 3
},
+/obj/item/autopsy_scanner,
/turf/open/floor/iron/white,
/area/ruin/space/ancientstation/delta/rnd)
"fw" = (
@@ -1531,9 +1532,9 @@
/area/ruin/space/ancientstation/delta/rnd)
"gP" = (
/obj/effect/decal/cleanable/dirt,
-/obj/structure/table,
-/obj/item/tank/internals/anesthetic,
-/obj/item/clothing/mask/breath/medical,
+/obj/machinery/computer/operating/oldstation{
+ dir = 4
+ },
/turf/open/floor/iron/white,
/area/ruin/space/ancientstation/delta/rnd)
"gQ" = (
@@ -2594,6 +2595,12 @@
/obj/effect/turf_decal/tile/yellow/half/contrasted,
/turf/open/floor/iron,
/area/ruin/space/ancientstation/beta/atmos)
+"lh" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/rnd/server/oldstation,
+/turf/open/floor/iron,
+/area/ruin/space/ancientstation/delta/rnd)
"lk" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/tile/brown/half/contrasted{
@@ -4910,14 +4917,6 @@
},
/turf/template_noop,
/area/space/nearstation)
-"zW" = (
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/decal/cleanable/dirt,
-/obj/structure/closet/crate/bin,
-/obj/effect/spawner/random/trash/garbage,
-/obj/effect/spawner/random/trash/garbage,
-/turf/open/floor/iron,
-/area/ruin/space/ancientstation/delta/rnd)
"zX" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/tile/yellow{
@@ -14186,7 +14185,7 @@ kw
Hk
kw
iq
-ze
+lh
WV
ob
hY
@@ -14384,7 +14383,7 @@ kw
jk
lF
hS
-zW
+ze
WV
ca
SI
diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm
index 34794b5b255..52ee2c87f4e 100644
--- a/code/__DEFINES/research.dm
+++ b/code/__DEFINES/research.dm
@@ -71,3 +71,17 @@
#define SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER 0.01
/// How much money is one point of gain worth.
#define SCIPAPER_GAIN_TO_MONEY 125
+
+///Connects the 'server_var' to a valid research server on your Z level.
+///Used for machines in LateInitialize, to ensure that RND servers are loaded first.
+#define CONNECT_TO_RND_SERVER_ROUNDSTART(server_var, holder) do { \
+ var/list/found_servers = SSresearch.get_available_servers(get_turf(holder)); \
+ var/obj/machinery/rnd/server/selected_server = length(found_servers) ? found_servers[1] : null; \
+ if (selected_server) { \
+ server_var = selected_server.stored_research; \
+ }; \
+ else { \
+ var/datum/techweb/station_fallback_web = locate(/datum/techweb/science) in SSresearch.techwebs; \
+ server_var = station_fallback_web; \
+ }; \
+} while (FALSE)
diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm
index 735dd1cdc57..7f0b52d471b 100644
--- a/code/controllers/subsystem/research.dm
+++ b/code/controllers/subsystem/research.dm
@@ -8,12 +8,9 @@ SUBSYSTEM_DEF(research)
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_designs = list() //associative id = node datum
- ///List of all techwebs.
+ ///List of all techwebs, generating points or not.
+ ///Autolathes, Mechfabs, and others all have shared techwebs, for example.
var/list/datum/techweb/techwebs = list()
- ///The default Science Techweb.
- var/datum/techweb/science/science_tech
- ///The default Admin Techweb.
- var/datum/techweb/admin/admin_tech
var/datum/techweb_node/error_node/error_node //These two are what you get if a node/design is deleted and somehow still stored in a console.
var/datum/design/error_design/error_design
@@ -74,8 +71,9 @@ SUBSYSTEM_DEF(research)
initialize_all_techweb_designs()
initialize_all_techweb_nodes()
populate_ordnance_experiments()
- science_tech = new /datum/techweb/science
- admin_tech = new /datum/techweb/admin
+ new /datum/techweb/science
+ new /datum/techweb/admin
+ new /datum/techweb/oldstation
autosort_categories()
error_design = new
error_node = new
@@ -308,3 +306,29 @@ SUBSYSTEM_DEF(research)
for (var/datum/experiment/ordnance/ordnance_experiment as anything in ordnance_experiments)
partner.accepted_experiments += ordnance_experiment.type
scientific_partners += partner
+
+/**
+ * Goes through all techwebs and goes through their servers to find ones on a valid z-level
+ * Returns the full list of all techweb servers.
+ */
+/datum/controller/subsystem/research/proc/get_available_servers(turf/location)
+ var/list/local_servers = list()
+ for (var/datum/techweb/individual_techweb as anything in techwebs)
+ var/list/servers = find_valid_servers(location, individual_techweb)
+ if(length(servers))
+ local_servers += servers
+ return local_servers
+
+/**
+ * Goes through an individual techweb's servers and finds one on a valid z-level
+ * Returns a list of existing ones, or an empty list otherwise.
+ * Args:
+ * - checking_web - The techweb we're checking the servers of.
+ */
+/datum/controller/subsystem/research/proc/find_valid_servers(turf/location, datum/techweb/checking_web)
+ var/list/valid_servers = list()
+ for(var/obj/machinery/rnd/server/server as anything in checking_web.techweb_servers)
+ if(!is_valid_z_level(get_turf(server), location))
+ continue
+ valid_servers += server
+ return valid_servers
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index ca3990fd9bc..1b10a7f2264 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -26,7 +26,6 @@
/obj/machinery/computer/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
-
power_change()
/obj/machinery/computer/process()
diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm
index a6a366dd390..47a202ae242 100644
--- a/code/game/machinery/computer/dna_console.dm
+++ b/code/game/machinery/computer/dna_console.dm
@@ -235,10 +235,13 @@
// Set the default tgui state
set_default_state()
+/obj/machinery/computer/scan_consolenew/LateInitialize()
+ . = ..()
// Link machine with research techweb. Used for discovering and accessing
// already discovered mutations
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- stored_research = SSresearch.science_tech
+ CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
+
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui)
. = ..()
diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm
index f512d92acb9..f7b0ef24ffd 100644
--- a/code/game/machinery/computer/operating_computer.dm
+++ b/code/game/machinery/computer/operating_computer.dm
@@ -17,13 +17,13 @@
/obj/machinery/computer/operating/Initialize(mapload)
. = ..()
- if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
- linked_techweb = SSresearch.science_tech
find_table()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/operating/LateInitialize()
. = ..()
+ if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
+ CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src)
experiment_handler = AddComponent( \
/datum/component/experiment_handler, \
diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
index 8af2c2bbfc6..a405ddd6004 100644
--- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm
@@ -1018,7 +1018,12 @@
build_path = /obj/machinery/rnd/server
req_components = list(
/obj/item/stack/cable_coil = 2,
- /datum/stock_part/scanning_module = 1)
+ /datum/stock_part/scanning_module = 1,
+ )
+
+/obj/item/circuitboard/machine/rdserver/oldstation
+ name = "Ancient R&D Server"
+ build_path = /obj/machinery/rnd/server/oldstation
/obj/item/circuitboard/machine/techfab/department/science
name = "\improper Departmental Techfab - Science"
diff --git a/code/modules/antagonists/ninja/ninjaDrainAct.dm b/code/modules/antagonists/ninja/ninjaDrainAct.dm
index 6d682482380..7eb827ec205 100644
--- a/code/modules/antagonists/ninja/ninjaDrainAct.dm
+++ b/code/modules/antagonists/ninja/ninjaDrainAct.dm
@@ -133,7 +133,7 @@
/obj/machinery/rnd/server/proc/ninjadrain_charge(mob/living/carbon/human/ninja, obj/item/mod/module/hacker/hacking_module)
if(!do_after(ninja, 30 SECONDS, target = src))
return
- SSresearch.science_tech.modify_points_all(0)
+ stored_research.modify_points_all(0)
to_chat(ninja, span_notice("Sabotage complete. Research notes corrupted."))
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
if(!ninja_antag)
diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
index 0966984c671..ff9678ad519 100644
--- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
+++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm
@@ -55,7 +55,8 @@
/// Handles interrupting research
/obj/machinery/shuttle_scrambler/proc/interrupt_research()
- for(var/obj/machinery/rnd/server/research_server as anything in SSresearch.science_tech.techweb_servers)
+ var/datum/techweb/science_web = locate(/datum/techweb/science) in SSresearch.techwebs
+ for(var/obj/machinery/rnd/server/research_server as anything in science_web.techweb_servers)
if(research_server.machine_stat & (NOPOWER|BROKEN|EMPED))
continue
research_server.emp_act(EMP_LIGHT)
diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm
index 4c0b6ae3b44..abc5d4ad1dd 100644
--- a/code/modules/experisci/experiment/handlers/experiment_handler.dm
+++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm
@@ -72,10 +72,7 @@
// Note this won't work at the moment for non-machines that have been included
// on the map as the servers aren't initialized when the non-machines are initializing
if (!(config_flags & EXPERIMENT_CONFIG_NO_AUTOCONNECT))
- var/list/found_servers = get_available_servers()
- var/obj/machinery/rnd/server/selected_server = length(found_servers) ? found_servers[1] : null
- if (selected_server)
- link_techweb(selected_server.stored_research)
+ CONNECT_TO_RND_SERVER_ROUNDSTART(linked_web, parent)
GLOB.experiment_handlers += src
@@ -328,32 +325,6 @@
// If we haven't returned yet then this shouldn't be allowed
return FALSE
-/**
- * Goes through all techwebs and goes through their servers to find ones on a valid z-level
- * Returns the full list of all techweb servers.
- */
-/datum/component/experiment_handler/proc/get_available_servers()
- var/list/local_servers = list()
- for (var/datum/techweb/techwebs as anything in SSresearch.techwebs)
- var/list/servers = find_valid_servers(techwebs)
- if(length(servers))
- local_servers += servers
- return local_servers
-
-/**
- * Goes through an individual techweb's servers and finds one on a valid z-level
- * Returns a list of existing ones, or an empty list otherwise.
- * Args:
- * - checking_web - The techweb we're checking the servers of.
- */
-/datum/component/experiment_handler/proc/find_valid_servers(datum/techweb/checking_web)
- var/list/valid_servers = list()
- for(var/obj/machinery/rnd/server/server as anything in checking_web.techweb_servers)
- if(!is_valid_z_level(get_turf(server), get_turf(parent)))
- continue
- valid_servers += server
- return valid_servers
-
/datum/component/experiment_handler/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
@@ -372,7 +343,7 @@
if(techwebs == linked_web) //disconnect if OUR techweb lost their servers.
unlink_techweb()
continue
- if(!length(find_valid_servers(techwebs)))
+ if(!length(SSresearch.find_valid_servers(get_turf(parent), techwebs)))
continue
var/list/data = list(
web_id = techwebs.id,
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_cytology.dm b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_cytology.dm
new file mode 100644
index 00000000000..72333ff67d1
--- /dev/null
+++ b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_cytology.dm
@@ -0,0 +1,29 @@
+/obj/item/petri_dish/oldstation
+ name = "molly's biopsy"
+ desc = "You can see a moldy piece of sandwich inside the dish. Maybe it helped to preserve the bacteria for that long."
+
+/obj/item/petri_dish/oldstation/Initialize(mapload)
+ . = ..()
+ sample = new
+ sample.GenerateSample(CELL_LINE_TABLE_COW, null, 1, 0)
+ var/datum/biological_sample/contamination = new
+ contamination.GenerateSample(CELL_LINE_TABLE_GRAPE, null, 1, 0)
+ sample.Merge(contamination)
+ sample.sample_color = COLOR_SAMPLE_BROWN
+ update_appearance()
+
+/obj/item/reagent_containers/cup/beaker/oldstation
+ name = "cultivation broth"
+ amount_per_transfer_from_this = 50
+ list_reagents = list(
+ // Required for CELL_LINE_TABLE_COW
+ /datum/reagent/consumable/nutriment/protein = 10,
+ /datum/reagent/consumable/nutriment = 5,
+ /datum/reagent/cellulose = 5,
+ // Required for CELL_LINE_TABLE_GRAPE
+ /datum/reagent/toxin/slimejelly = 5,
+ /datum/reagent/yuck = 5,
+ /datum/reagent/consumable/vitfro = 5,
+ // Supplementary for CELL_LINE_TABLE_GRAPE
+ /datum/reagent/consumable/liquidgibs = 5
+ )
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/oldstation.dm b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_fluff.dm
similarity index 64%
rename from code/modules/mapfluff/ruins/spaceruin_code/oldstation.dm
rename to code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_fluff.dm
index 4ad5c4aad09..a0b4adb9f75 100644
--- a/code/modules/mapfluff/ruins/spaceruin_code/oldstation.dm
+++ b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_fluff.dm
@@ -108,159 +108,3 @@
name = "DO NOT TOUCH!"
default_raw_text = "This is a spare pre-charged APC battery for emergencies ONLY. DO NOT use it for stun prods, Bob.
\
Note: Use crowbar to remove the APC cover and take out the malfunctioning battery."
-
-/obj/machinery/mod_installer
- name = "modular outerwear device installator"
- desc = "An ancient machine that mounts a MOD unit onto the occupant."
- icon = 'icons/obj/machines/mod_installer.dmi'
- icon_state = "mod_installer"
- base_icon_state = "mod_installer"
- layer = ABOVE_WINDOW_LAYER
- use_power = IDLE_POWER_USE
- anchored = TRUE
- density = TRUE
- obj_flags = BLOCKS_CONSTRUCTION // Becomes undense when the door is open
- idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.5
- active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.3
-
- var/busy = FALSE
- var/busy_icon_state
-
- var/obj/item/mod/control/mod_unit = /obj/item/mod/control/pre_equipped/prototype
-
- COOLDOWN_DECLARE(message_cooldown)
-
-/obj/machinery/mod_installer/Initialize(mapload)
- . = ..()
- occupant_typecache = typecacheof(/mob/living/carbon/human)
- if(ispath(mod_unit))
- mod_unit = new mod_unit()
-
-/obj/machinery/mod_installer/Destroy()
- QDEL_NULL(mod_unit)
- return ..()
-
-/obj/machinery/mod_installer/proc/set_busy(status, working_icon)
- busy = status
- busy_icon_state = working_icon
- update_appearance()
-
-/obj/machinery/mod_installer/proc/play_install_sound()
- playsound(src, 'sound/items/rped.ogg', 30, FALSE)
-
-/obj/machinery/mod_installer/update_icon_state()
- icon_state = busy ? busy_icon_state : "[base_icon_state][state_open ? "_open" : null]"
- return ..()
-
-/obj/machinery/mod_installer/update_overlays()
- var/list/overlays = ..()
- if(machine_stat & (NOPOWER|BROKEN))
- return overlays
- overlays += (busy || !mod_unit) ? "red" : "green"
- return overlays
-
-/obj/machinery/mod_installer/proc/start_process()
- if(machine_stat & (NOPOWER|BROKEN))
- return
- if(!occupant || !mod_unit || busy)
- return
- set_busy(TRUE, "[initial(icon_state)]_raising")
- addtimer(CALLBACK(src, PROC_REF(set_busy), TRUE, "[initial(icon_state)]_active"), 2.5 SECONDS)
- addtimer(CALLBACK(src, PROC_REF(play_install_sound)), 2.5 SECONDS)
- addtimer(CALLBACK(src, PROC_REF(set_busy), TRUE, "[initial(icon_state)]_falling"), 5 SECONDS)
- addtimer(CALLBACK(src, PROC_REF(complete_process)), 7.5 SECONDS)
-
-/obj/machinery/mod_installer/proc/complete_process()
- set_busy(FALSE)
- var/mob/living/carbon/human/human_occupant = occupant
- if(!istype(human_occupant))
- return
- if(!human_occupant.dropItemToGround(human_occupant.back))
- return
- if(!human_occupant.equip_to_slot_if_possible(mod_unit, mod_unit.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
- return
- human_occupant.update_action_buttons(TRUE)
- playsound(src, 'sound/machines/ping.ogg', 30, FALSE)
- if(!human_occupant.dropItemToGround(human_occupant.wear_suit) || !human_occupant.dropItemToGround(human_occupant.head))
- finish_completion()
- return
- mod_unit.quick_activation()
- finish_completion()
-
-/obj/machinery/mod_installer/proc/finish_completion()
- mod_unit = null
- open_machine()
-
-/obj/machinery/mod_installer/open_machine(drop = TRUE, density_to_set = FALSE)
- if(state_open)
- return FALSE
- ..()
- return TRUE
-
-/obj/machinery/mod_installer/close_machine(mob/living/carbon/user, density_to_set = TRUE)
- if(!state_open)
- return FALSE
- ..()
- addtimer(CALLBACK(src, PROC_REF(start_process)), 1 SECONDS)
- return TRUE
-
-/obj/machinery/mod_installer/relaymove(mob/living/user, direction)
- var/message
- if(busy)
- message = "it won't budge!"
- else if(user.stat != CONSCIOUS)
- message = "you don't have the energy!"
- if(!isnull(message))
- if (COOLDOWN_FINISHED(src, message_cooldown))
- COOLDOWN_START(src, message_cooldown, 5 SECONDS)
- balloon_alert(user, message)
- return
- open_machine()
-
-/obj/machinery/mod_installer/interact(mob/user)
- if(state_open)
- close_machine(null, user)
- return
- else if(busy)
- balloon_alert(user, "it's locked!")
- return
- open_machine()
-
-/obj/item/petri_dish/oldstation
- name = "molly's biopsy"
- desc = "You can see a moldy piece of sandwich inside the dish. Maybe it helped to preserve the bacteria for that long."
-
-/obj/item/petri_dish/oldstation/Initialize(mapload)
- . = ..()
- sample = new
- sample.GenerateSample(CELL_LINE_TABLE_COW, null, 1, 0)
- var/datum/biological_sample/contamination = new
- contamination.GenerateSample(CELL_LINE_TABLE_GRAPE, null, 1, 0)
- sample.Merge(contamination)
- sample.sample_color = COLOR_SAMPLE_BROWN
- update_appearance()
-
-/obj/item/reagent_containers/cup/beaker/oldstation
- name = "cultivation broth"
- amount_per_transfer_from_this = 50
- list_reagents = list(
- // Required for CELL_LINE_TABLE_COW
- /datum/reagent/consumable/nutriment/protein = 10,
- /datum/reagent/consumable/nutriment = 5,
- /datum/reagent/cellulose = 5,
- // Required for CELL_LINE_TABLE_GRAPE
- /datum/reagent/toxin/slimejelly = 5,
- /datum/reagent/yuck = 5,
- /datum/reagent/consumable/vitfro = 5,
- // Supplementary for CELL_LINE_TABLE_GRAPE
- /datum/reagent/consumable/liquidgibs = 5
- )
-
-/obj/machinery/computer/old
- name = "old computer"
- circuit = /obj/item/circuitboard/computer
-
-/obj/machinery/computer/old/Initialize(mapload)
- icon_keyboard = pick("generic_key", "med_key")
- icon_screen = pick("generic", "comm_monitor", "comm_logs")
- . = ..()
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_machines.dm b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_machines.dm
new file mode 100644
index 00000000000..c2552b10744
--- /dev/null
+++ b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_machines.dm
@@ -0,0 +1,8 @@
+/obj/machinery/computer/old
+ name = "old computer"
+ circuit = /obj/item/circuitboard/computer
+
+/obj/machinery/computer/old/Initialize(mapload)
+ icon_keyboard = pick("generic_key", "med_key")
+ icon_screen = pick("generic", "comm_monitor", "comm_logs")
+ return ..()
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm
new file mode 100644
index 00000000000..ac026045674
--- /dev/null
+++ b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_mod.dm
@@ -0,0 +1,116 @@
+/obj/machinery/mod_installer
+ name = "modular outerwear device installator"
+ desc = "An ancient machine that mounts a MOD unit onto the occupant."
+ icon = 'icons/obj/machines/mod_installer.dmi'
+ icon_state = "mod_installer"
+ base_icon_state = "mod_installer"
+ layer = ABOVE_WINDOW_LAYER
+ use_power = IDLE_POWER_USE
+ anchored = TRUE
+ density = TRUE
+ obj_flags = BLOCKS_CONSTRUCTION // Becomes undense when the door is open
+ idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.5
+ active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.3
+
+ var/busy = FALSE
+ var/busy_icon_state
+
+ var/obj/item/mod/control/mod_unit = /obj/item/mod/control/pre_equipped/prototype
+
+ COOLDOWN_DECLARE(message_cooldown)
+
+/obj/machinery/mod_installer/Initialize(mapload)
+ . = ..()
+ occupant_typecache = typecacheof(/mob/living/carbon/human)
+ if(ispath(mod_unit))
+ mod_unit = new mod_unit()
+
+/obj/machinery/mod_installer/Destroy()
+ QDEL_NULL(mod_unit)
+ return ..()
+
+/obj/machinery/mod_installer/proc/set_busy(status, working_icon)
+ busy = status
+ busy_icon_state = working_icon
+ update_appearance()
+
+/obj/machinery/mod_installer/proc/play_install_sound()
+ playsound(src, 'sound/items/rped.ogg', 30, FALSE)
+
+/obj/machinery/mod_installer/update_icon_state()
+ icon_state = busy ? busy_icon_state : "[base_icon_state][state_open ? "_open" : null]"
+ return ..()
+
+/obj/machinery/mod_installer/update_overlays()
+ var/list/overlays = ..()
+ if(machine_stat & (NOPOWER|BROKEN))
+ return overlays
+ overlays += (busy || !mod_unit) ? "red" : "green"
+ return overlays
+
+/obj/machinery/mod_installer/proc/start_process()
+ if(machine_stat & (NOPOWER|BROKEN))
+ return
+ if(!occupant || !mod_unit || busy)
+ return
+ set_busy(TRUE, "[initial(icon_state)]_raising")
+ addtimer(CALLBACK(src, PROC_REF(set_busy), TRUE, "[initial(icon_state)]_active"), 2.5 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(play_install_sound)), 2.5 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(set_busy), TRUE, "[initial(icon_state)]_falling"), 5 SECONDS)
+ addtimer(CALLBACK(src, PROC_REF(complete_process)), 7.5 SECONDS)
+
+/obj/machinery/mod_installer/proc/complete_process()
+ set_busy(FALSE)
+ var/mob/living/carbon/human/human_occupant = occupant
+ if(!istype(human_occupant))
+ return
+ if(!human_occupant.dropItemToGround(human_occupant.back))
+ return
+ if(!human_occupant.equip_to_slot_if_possible(mod_unit, mod_unit.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
+ return
+ human_occupant.update_action_buttons(TRUE)
+ playsound(src, 'sound/machines/ping.ogg', 30, FALSE)
+ if(!human_occupant.dropItemToGround(human_occupant.wear_suit) || !human_occupant.dropItemToGround(human_occupant.head))
+ finish_completion()
+ return
+ mod_unit.quick_activation()
+ finish_completion()
+
+/obj/machinery/mod_installer/proc/finish_completion()
+ mod_unit = null
+ open_machine()
+
+/obj/machinery/mod_installer/open_machine(drop = TRUE, density_to_set = FALSE)
+ if(state_open)
+ return FALSE
+ ..()
+ return TRUE
+
+/obj/machinery/mod_installer/close_machine(mob/living/carbon/user, density_to_set = TRUE)
+ if(!state_open)
+ return FALSE
+ ..()
+ addtimer(CALLBACK(src, PROC_REF(start_process)), 1 SECONDS)
+ return TRUE
+
+/obj/machinery/mod_installer/relaymove(mob/living/user, direction)
+ var/message
+ if(busy)
+ message = "it won't budge!"
+ else if(user.stat != CONSCIOUS)
+ message = "you don't have the energy!"
+ if(!isnull(message))
+ if (COOLDOWN_FINISHED(src, message_cooldown))
+ COOLDOWN_START(src, message_cooldown, 5 SECONDS)
+ balloon_alert(user, message)
+ return
+ open_machine()
+
+/obj/machinery/mod_installer/interact(mob/user)
+ if(state_open)
+ close_machine(null, user)
+ return
+ else if(busy)
+ balloon_alert(user, "it's locked!")
+ return
+ open_machine()
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_rnd.dm b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_rnd.dm
new file mode 100644
index 00000000000..58d14e0d041
--- /dev/null
+++ b/code/modules/mapfluff/ruins/spaceruin_code/oldstation/oldstation_rnd.dm
@@ -0,0 +1,29 @@
+/obj/machinery/rnd/server/oldstation
+ name = "\improper Ancient R&D Server"
+ circuit = /obj/item/circuitboard/machine/rdserver/oldstation
+ req_access = list(ACCESS_AWAY_SCIENCE)
+
+/obj/machinery/rnd/server/oldstation/Initialize(mapload)
+ register_context()
+ var/datum/techweb/oldstation_web = locate(/datum/techweb/oldstation) in SSresearch.techwebs
+ stored_research = oldstation_web
+ return ..()
+
+/obj/machinery/rnd/server/oldstation/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ if(held_item && istype(held_item, /obj/item/research_notes))
+ context[SCREENTIP_CONTEXT_LMB] = "Generate research points"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/machinery/rnd/server/oldstation/attackby(obj/item/attacking_item, mob/user, params)
+ if(istype(attacking_item, /obj/item/research_notes) && stored_research)
+ var/obj/item/research_notes/research_notes = attacking_item
+ stored_research.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = research_notes.value))
+ playsound(src, 'sound/machines/copier.ogg', 50, TRUE)
+ qdel(research_notes)
+ return
+ return ..()
+
+///Ancient computer that starts with dissection to tell players they have it.
+/obj/machinery/computer/operating/oldstation
+ name = "ancient operating computer"
+ advanced_surgeries = list(/datum/surgery/advanced/experimental_dissection)
diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm
index faf02013bf4..eae3e046aed 100644
--- a/code/modules/mob/living/simple_animal/bot/medbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/medbot.dm
@@ -211,8 +211,6 @@
if(!isnull(new_skin))
skin = new_skin
update_appearance()
- if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
- linked_techweb = SSresearch.science_tech
AddComponent(/datum/component/tippable, \
tip_time = 3 SECONDS, \
@@ -221,6 +219,12 @@
pre_tipped_callback = CALLBACK(src, PROC_REF(pre_tip_over)), \
post_tipped_callback = CALLBACK(src, PROC_REF(after_tip_over)), \
post_untipped_callback = CALLBACK(src, PROC_REF(after_righted)))
+ return INITIALIZE_HINT_LATELOAD
+
+/mob/living/simple_animal/bot/medbot/LateInitialize()
+ . = ..()
+ if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
+ CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src)
/mob/living/simple_animal/bot/medbot/bot_reset()
..()
diff --git a/code/modules/modular_computers/file_system/programs/frontier.dm b/code/modules/modular_computers/file_system/programs/frontier.dm
index aa897467a8c..cf6cc4b2bc2 100644
--- a/code/modules/modular_computers/file_system/programs/frontier.dm
+++ b/code/modules/modular_computers/file_system/programs/frontier.dm
@@ -25,7 +25,7 @@
/datum/computer_file/program/scipaper_program/on_start(mob/living/user)
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
- linked_techweb = SSresearch.science_tech
+ CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src)
/datum/computer_file/program/scipaper_program/application_attackby(obj/item/attacking_item, mob/living/user)
if(!istype(attacking_item, /obj/item/multitool))
diff --git a/code/modules/modular_computers/file_system/programs/techweb.dm b/code/modules/modular_computers/file_system/programs/techweb.dm
index 52129d39997..9c097b2fb9b 100644
--- a/code/modules/modular_computers/file_system/programs/techweb.dm
+++ b/code/modules/modular_computers/file_system/programs/techweb.dm
@@ -24,7 +24,7 @@
/datum/computer_file/program/science/on_start(mob/living/user)
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- stored_research = SSresearch.science_tech
+ CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
/datum/computer_file/program/science/application_attackby(obj/item/attacking_item, mob/living/user)
if(!istype(attacking_item, /obj/item/multitool))
@@ -194,7 +194,7 @@
var/list/price = tech_node.get_price(stored_research)
if(stored_research.can_afford(price))
user.investigate_log("researched [id]([json_encode(price)]) on techweb id [stored_research.id] via [computer].", INVESTIGATE_RESEARCH)
- if(stored_research == SSresearch.science_tech)
+ if(istype(stored_research, /datum/techweb/science))
SSblackbox.record_feedback("associative", "science_techweb_unlock", 1, list("id" = "[id]", "name" = tech_node.display_name, "price" = "[json_encode(price)]", "time" = SQLtime()))
if(stored_research.research_node_id(id))
computer.say("Successfully researched [tech_node.display_name].")
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index 33d866a659b..2bb779e318b 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -1113,3 +1113,10 @@
id = "surgery_wing_reconstruction"
surgery = /datum/surgery/advanced/wing_reconstruction
research_icon_state = "surgery_chest"
+
+/datum/design/surgery/experimental_dissection
+ name = "Experimental Dissection"
+ desc = "An experimental surgical procedure that dissects bodies in exchange for research points at ancient R&D consoles."
+ id = "surgery_oldstation_dissection"
+ surgery = /datum/surgery/advanced/experimental_dissection
+ research_icon_state = "surgery_chest"
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index 155985ad3a0..c4983ad6c81 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -168,11 +168,12 @@
for(var/node_id in listin)
var/datum/techweb_node/N = SSresearch.techweb_node_by_id(node_id)
var/str = "[N.display_name]: [listin[N]] points."
- if(SSresearch.science_tech.researched_nodes[N.id])
+ var/datum/techweb/science_web = locate(/datum/techweb/science) in SSresearch.techwebs
+ if(science_web.researched_nodes[N.id])
res += str
- else if(SSresearch.science_tech.boosted_nodes[N.id])
+ else if(science_web.boosted_nodes[N.id])
boosted += str
- if(SSresearch.science_tech.visible_nodes[N.id]) //JOY OF DISCOVERY!
+ if(science_web.visible_nodes[N.id]) //JOY OF DISCOVERY!
output += str
output += boosted + res
dat += output
diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm
index d607a5573a0..e5a426d3a1e 100644
--- a/code/modules/research/machinery/_production.dm
+++ b/code/modules/research/machinery/_production.dm
@@ -46,22 +46,22 @@
)
create_reagents(0, OPENCONTAINER)
- if(stored_research)
- update_designs()
RefreshParts()
update_icon(UPDATE_OVERLAYS)
/obj/machinery/rnd/production/connect_techweb(datum/techweb/new_techweb)
if(stored_research)
UnregisterSignal(stored_research, list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN))
+ return ..()
+/obj/machinery/rnd/production/on_connected_techweb()
. = ..()
-
RegisterSignals(
stored_research,
list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN),
PROC_REF(on_techweb_update)
)
+ update_designs()
/obj/machinery/rnd/production/Destroy()
materials = null
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index 10fdb6fe211..fdfcf9bf72d 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -45,10 +45,10 @@ Nothing else in the console has ID requirements.
return reagent.name
return ID
-/obj/machinery/computer/rdconsole/Initialize(mapload)
+/obj/machinery/computer/rdconsole/LateInitialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- stored_research = SSresearch.science_tech
+ CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
if(stored_research)
stored_research.consoles_accessing += src
@@ -107,7 +107,7 @@ Nothing else in the console has ID requirements.
var/list/price = TN.get_price(stored_research)
if(stored_research.can_afford(price))
user.investigate_log("researched [id]([json_encode(price)]) on techweb id [stored_research.id].", INVESTIGATE_RESEARCH)
- if(stored_research == SSresearch.science_tech)
+ if(istype(stored_research, /datum/techweb/science))
SSblackbox.record_feedback("associative", "science_techweb_unlock", 1, list("id" = "[id]", "name" = TN.display_name, "price" = "[json_encode(price)]", "time" = SQLtime()))
if(stored_research.research_node_id(id))
say("Successfully researched [TN.display_name].")
diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm
index bb19fb34817..3047c3e1a9a 100644
--- a/code/modules/research/rdmachines.dm
+++ b/code/modules/research/rdmachines.dm
@@ -20,10 +20,15 @@
/obj/machinery/rnd/Initialize(mapload)
. = ..()
- if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- connect_techweb(SSresearch.science_tech)
set_wires(new /datum/wires/rnd(src))
+/obj/machinery/rnd/LateInitialize()
+ . = ..()
+ if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
+ CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
+ if(stored_research)
+ on_connected_techweb()
+
/obj/machinery/rnd/Destroy()
if(stored_research)
log_research("[src] disconnected from techweb [stored_research] (destroyed).")
@@ -31,10 +36,17 @@
QDEL_NULL(wires)
return ..()
+///Called when attempting to connect the machine to a techweb, forgetting the old.
/obj/machinery/rnd/proc/connect_techweb(datum/techweb/new_techweb)
if(stored_research)
log_research("[src] disconnected from techweb [stored_research] when connected to [new_techweb].")
stored_research = new_techweb
+ if(!isnull(stored_research))
+ on_connected_techweb()
+
+///Called post-connection to a new techweb.
+/obj/machinery/rnd/proc/on_connected_techweb()
+ SHOULD_CALL_PARENT(FALSE)
/obj/machinery/rnd/proc/shock(mob/user, prb)
if(machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock
diff --git a/code/modules/research/research_disk.dm b/code/modules/research/research_disk.dm
index 8205fc230c4..43fcd208fcb 100644
--- a/code/modules/research/research_disk.dm
+++ b/code/modules/research/research_disk.dm
@@ -19,5 +19,5 @@
custom_materials = null
/obj/item/disk/tech_disk/debug/Initialize(mapload)
- stored_research = SSresearch.admin_tech
+ stored_research = locate(/datum/techweb/admin) in SSresearch.techwebs
return ..()
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 7665082f698..b79bf3f8e02 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -27,8 +27,14 @@
/obj/machinery/rnd/server/Initialize(mapload)
. = ..()
- if(CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- stored_research = new /datum/techweb
+ //servers handle techwebs differently as we are expected to be there to connect
+ //every other machinery on-station.
+ if(!stored_research)
+ if(CONFIG_GET(flag/no_default_techweb_link))
+ stored_research = new /datum/techweb
+ else
+ var/datum/techweb/science_web = locate(/datum/techweb/science) in SSresearch.techwebs
+ connect_techweb(science_web)
stored_research.techweb_servers |= src
name += " [num2hex(rand(1,65535), -1)]" //gives us a random four-digit hex number as part of the name. Y'know, for fluff.
diff --git a/code/modules/research/server_control.dm b/code/modules/research/server_control.dm
index da6cb322be8..94a429dc6d7 100644
--- a/code/modules/research/server_control.dm
+++ b/code/modules/research/server_control.dm
@@ -9,10 +9,10 @@
///Connected techweb node the server is connected to.
var/datum/techweb/stored_research
-/obj/machinery/computer/rdservercontrol/Initialize(mapload, obj/item/circuitboard/C)
+/obj/machinery/computer/rdservercontrol/LateInitialize()
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- stored_research = SSresearch.science_tech
+ CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
/obj/machinery/computer/rdservercontrol/multitool_act(mob/living/user, obj/item/multitool/tool)
if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index 1ffae0a48dd..521504da351 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -216,7 +216,8 @@
else
researched_designs[design.id] = TRUE
- hidden_nodes -= design.id
+ for(var/list/datum/techweb_node/unlocked_nodes as anything in design.unlocked_by)
+ hidden_nodes -= unlocked_nodes
return TRUE
diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm
index 6ab7d68beba..2f01252548a 100644
--- a/code/modules/research/techweb/_techweb_node.dm
+++ b/code/modules/research/techweb/_techweb_node.dm
@@ -88,11 +88,12 @@
if(actual_costs[booster])
var/delta = max(0, actual_costs[booster] - 250)
actual_costs[booster] -= min(boostlist[booster], delta)
-
+
return actual_costs
/datum/techweb_node/proc/price_display(datum/techweb/TN)
return techweb_point_display_generic(get_price(TN))
-/datum/techweb_node/proc/on_research() //new proc, not currently in file
- return
+///Proc called when the Station (Science techweb specific) researches a node.
+/datum/techweb_node/proc/on_station_research()
+ SHOULD_CALL_PARENT(FALSE)
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 393cdc4b9d2..e3fcdba9d64 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -499,6 +499,16 @@
)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000)
+/datum/techweb_node/oldstation_surgery
+ id = "oldstation_surgery"
+ display_name = "Experimental Dissection"
+ description = "Grants access to experimental dissections, which allows generation of research points."
+ design_ids = list(
+ "surgery_oldstation_dissection",
+ )
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500)
+ hidden = TRUE
+ show_on_wiki = FALSE
/datum/techweb_node/adv_surgery
id = "adv_surgery"
@@ -2119,8 +2129,8 @@
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
hidden = TRUE
-/datum/techweb_node/alientech/on_research() //Unlocks the Zeta shuttle for purchase
- SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH] = TRUE
+/datum/techweb_node/alientech/on_station_research()
+ SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH] = TRUE
/datum/techweb_node/alien_bio
id = "alien_bio"
diff --git a/code/modules/research/techweb/techweb_types.dm b/code/modules/research/techweb/techweb_types.dm
index 1f226793624..c01b1226a4c 100644
--- a/code/modules/research/techweb/techweb_types.dm
+++ b/code/modules/research/techweb/techweb_types.dm
@@ -6,18 +6,26 @@
organization = "Nanotrasen"
should_generate_points = TRUE
-//When something is researched, triggers the proc for this techweb only
/datum/techweb/science/research_node(datum/techweb_node/node, force = FALSE, auto_adjust_cost = TRUE, get_that_dosh = TRUE)
. = ..()
if(.)
- node.on_research()
+ node.on_station_research()
+
+/datum/techweb/oldstation
+ id = "CHARLIE"
+ organization = "Nanotrasen"
+ should_generate_points = TRUE
+
+/datum/techweb/oldstation/New()
+ . = ..()
+ research_node_id("oldstation_surgery", TRUE, TRUE, FALSE)
/**
* Admin techweb that has everything unlocked by default
*/
/datum/techweb/admin
id = "ADMIN"
- organization = "CentCom"
+ organization = "Central Command"
/datum/techweb/admin/New()
. = ..()
diff --git a/code/modules/surgery/autopsy.dm b/code/modules/surgery/autopsy.dm
index 9bd232e4c0d..2d106cfd441 100644
--- a/code/modules/surgery/autopsy.dm
+++ b/code/modules/surgery/autopsy.dm
@@ -13,7 +13,7 @@
. = ..()
if(patient.stat != DEAD)
return FALSE
- if(HAS_TRAIT(patient, TRAIT_DISSECTED))
+ if(HAS_TRAIT_FROM(patient, TRAIT_DISSECTED, AUTOPSY_TRAIT))
return FALSE
return TRUE
diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm
new file mode 100644
index 00000000000..6ae5e447e0b
--- /dev/null
+++ b/code/modules/surgery/experimental_dissection.dm
@@ -0,0 +1,152 @@
+///How many research points you gain from dissecting a Human.
+#define BASE_HUMAN_REWARD 500
+
+/datum/surgery/advanced/experimental_dissection
+ name = "Experimental Dissection"
+ desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database."
+ steps = list(
+ /datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/experimental_dissection,
+ /datum/surgery_step/close,
+ )
+ surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_MORBID_CURIOSITY
+ possible_locs = list(BODY_ZONE_CHEST)
+ target_mobtypes = list(/mob/living)
+
+/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/target)
+ . = ..()
+ if(HAS_TRAIT_FROM(target, TRAIT_DISSECTED, EXPERIMENTAL_SURGERY_TRAIT))
+ return FALSE
+ if(target.stat != DEAD)
+ return FALSE
+
+/datum/surgery_step/experimental_dissection
+ name = "dissection"
+ implements = list(
+ /obj/item/autopsy_scanner = 100,
+ TOOL_SCALPEL = 60,
+ TOOL_KNIFE = 20,
+ /obj/item/shard = 10,
+ )
+ time = 12 SECONDS
+ silicons_obey_prob = TRUE
+
+/datum/surgery_step/experimental_dissection/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ user.visible_message("[user] starts dissecting [target].", "You start dissecting [target].")
+
+/datum/surgery_step/experimental_dissection/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE)
+ var/points_earned = check_value(target)
+ user.visible_message("[user] dissects [target], discovering [points_earned] point\s of data!", "You dissect [target], finding [points_earned] point\s worth of discoveries, you also write a few notes.")
+
+ var/obj/item/research_notes/the_dossier = new /obj/item/research_notes(user.loc, points_earned, "biology")
+ if(!user.put_in_hands(the_dossier) && istype(user.get_inactive_held_item(), /obj/item/research_notes))
+ var/obj/item/research_notes/hand_dossier = user.get_inactive_held_item()
+ hand_dossier.merge(the_dossier)
+
+ var/obj/item/bodypart/target_chest = target.get_bodypart(BODY_ZONE_CHEST)
+ target.apply_damage(80, BRUTE, target_chest)
+ ADD_TRAIT(target, TRAIT_DISSECTED, EXPERIMENTAL_SURGERY_TRAIT)
+ return ..()
+
+/datum/surgery_step/experimental_dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/points_earned = round(check_value(target) * 0.01)
+ user.visible_message(
+ "[user] dissects [target]!",
+ "You dissect [target], but do not find anything particularly interesting.",
+ )
+
+ var/obj/item/research_notes/the_dossier = new /obj/item/research_notes(user.loc, points_earned, "biology")
+ if(!user.put_in_hands(the_dossier) && istype(user.get_inactive_held_item(), /obj/item/research_notes))
+ var/obj/item/research_notes/hand_dossier = user.get_inactive_held_item()
+ hand_dossier.merge(the_dossier)
+
+ var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
+ target.apply_damage(80, BRUTE, L)
+ return TRUE
+
+///Calculates how many research points dissecting 'target' is worth.
+/datum/surgery_step/experimental_dissection/proc/check_value(mob/living/target)
+ var/cost = BASE_HUMAN_REWARD
+
+ if(ishuman(target))
+ var/mob/living/carbon/human/human_target = target
+ if(human_target.dna?.species)
+ if(ismonkey(human_target))
+ cost /= 5
+ else if(isabductor(human_target))
+ cost *= 4
+ else if(isgolem(human_target) || iszombie(human_target))
+ cost *= 3
+ else if(isjellyperson(human_target) || ispodperson(human_target))
+ cost *= 2
+ else if(isalienroyal(target))
+ cost *= 10
+ else if(isalienadult(target))
+ cost *= 5
+ else
+ cost /= 6
+
+ return cost
+
+#undef BASE_HUMAN_REWARD
+
+/obj/item/research_notes
+ name = "research notes"
+ desc = "Valuable scientific data. Use it in an ancient research server to turn it in."
+ icon = 'icons/obj/service/bureaucracy.dmi'
+ icon_state = "paper"
+ w_class = WEIGHT_CLASS_SMALL
+ ///research points it holds
+ var/value = 100
+ ///origin of the research
+ var/origin_type = "debug"
+ ///if it ws merged with different origins to apply a bonus
+ var/mixed = FALSE
+
+/obj/item/research_notes/Initialize(mapload, value, origin_type)
+ . = ..()
+ if(value)
+ src.value = value
+ if(origin_type)
+ src.origin_type = origin_type
+ change_vol()
+
+/obj/item/research_notes/examine(mob/user)
+ . = ..()
+ . += span_notice("It is worth [value] research points.")
+
+/obj/item/research_notes/attackby(obj/item/attacking_item, mob/living/user, params)
+ if(istype(attacking_item, /obj/item/research_notes))
+ var/obj/item/research_notes/notes = attacking_item
+ value = value + notes.value
+ change_vol()
+ qdel(notes)
+ return
+ return ..()
+
+/// proc that changes name and icon depending on value
+/obj/item/research_notes/proc/change_vol()
+ if(value >= 10000)
+ name = "revolutionary discovery in the field of [origin_type]"
+ icon_state = "docs_verified"
+ else if(value >= 2500)
+ name = "essay about [origin_type]"
+ icon_state = "paper_words"
+ else if(value >= 100)
+ name = "notes of [origin_type]"
+ icon_state = "paperslip_words"
+ else
+ name = "fragmentary data of [origin_type]"
+ icon_state = "scrap"
+
+///proc when you slap research notes into another one, it applies a bonus if they are of different origin (only applied once)
+/obj/item/research_notes/proc/merge(obj/item/research_notes/new_paper)
+ var/bonus = min(value , new_paper.value)
+ value = value + new_paper.value
+ if(origin_type != new_paper.origin_type && !mixed)
+ value += bonus * 0.3
+ origin_type = "[origin_type] and [new_paper.origin_type]"
+ mixed = TRUE
+ change_vol()
+ qdel(new_paper)
diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm
index 618ad33d1db..56b3cd2138c 100644
--- a/code/modules/vehicles/mecha/mech_fabricator.dm
+++ b/code/modules/vehicles/mecha/mech_fabricator.dm
@@ -50,8 +50,6 @@
var/list/datum/design/cached_designs
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
- if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
- connect_techweb(SSresearch.science_tech)
rmat = AddComponent( \
/datum/component/remote_materials, \
mapload && link_on_init, \
@@ -59,20 +57,29 @@
)
cached_designs = list()
RefreshParts() //Recalculating local material sizes if the fab isn't linked
- if(stored_research)
- update_menu_tech()
return ..()
+/obj/machinery/mecha_part_fabricator/LateInitialize()
+ . = ..()
+ if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
+ CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, src)
+ if(stored_research)
+ on_connected_techweb()
+
/obj/machinery/mecha_part_fabricator/proc/connect_techweb(datum/techweb/new_techweb)
if(stored_research)
UnregisterSignal(stored_research, list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN))
-
stored_research = new_techweb
+ if(!isnull(stored_research))
+ on_connected_techweb()
+
+/obj/machinery/mecha_part_fabricator/proc/on_connected_techweb()
RegisterSignals(
stored_research,
list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN),
PROC_REF(on_techweb_update)
)
+ update_menu_tech()
/obj/machinery/mecha_part_fabricator/multitool_act(mob/living/user, obj/item/multitool/tool)
if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
diff --git a/code/modules/wiremod/core/component_printer.dm b/code/modules/wiremod/core/component_printer.dm
index cf791ffdad6..25c684c5a28 100644
--- a/code/modules/wiremod/core/component_printer.dm
+++ b/code/modules/wiremod/core/component_printer.dm
@@ -22,21 +22,27 @@
/obj/machinery/component_printer/Initialize(mapload)
. = ..()
- if(!CONFIG_GET(flag/no_default_techweb_link) && !techweb)
- connect_techweb(SSresearch.science_tech)
-
materials = AddComponent( \
/datum/component/remote_materials, \
mapload, \
mat_container_flags = BREAKDOWN_FLAGS_LATHE, \
)
+/obj/machinery/component_printer/LateInitialize()
+ . = ..()
+ if(!CONFIG_GET(flag/no_default_techweb_link) && !techweb)
+ CONNECT_TO_RND_SERVER_ROUNDSTART(techweb, src)
+ if(techweb)
+ on_connected_techweb()
+
/obj/machinery/component_printer/proc/connect_techweb(datum/techweb/new_techweb)
if(techweb)
UnregisterSignal(techweb, list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN))
-
techweb = new_techweb
+ if(!isnull(techweb))
+ on_connected_techweb()
+/obj/machinery/component_printer/proc/on_connected_techweb()
for (var/researched_design_id in techweb.researched_designs)
var/datum/design/design = SSresearch.techweb_design_by_id(researched_design_id)
if (!(design.build_type & COMPONENT_PRINTER) || !ispath(design.build_path, /obj/item/circuit_component))
diff --git a/tgstation.dme b/tgstation.dme
index f83a39b628c..2d88e54f844 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4034,7 +4034,6 @@
#include "code\modules\mapfluff\ruins\spaceruin_code\interdyne.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\listeningstation.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\meateor.dm"
-#include "code\modules\mapfluff\ruins\spaceruin_code\oldstation.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\originalcontent.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\spacehotel.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\the_Outlet.dm"
@@ -4042,6 +4041,11 @@
#include "code\modules\mapfluff\ruins\spaceruin_code\waystation.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\whiteship.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\whiteshipruin_box.dm"
+#include "code\modules\mapfluff\ruins\spaceruin_code\oldstation\oldstation_cytology.dm"
+#include "code\modules\mapfluff\ruins\spaceruin_code\oldstation\oldstation_fluff.dm"
+#include "code\modules\mapfluff\ruins\spaceruin_code\oldstation\oldstation_machines.dm"
+#include "code\modules\mapfluff\ruins\spaceruin_code\oldstation\oldstation_mod.dm"
+#include "code\modules\mapfluff\ruins\spaceruin_code\oldstation\oldstation_rnd.dm"
#include "code\modules\mapping\access_helpers.dm"
#include "code\modules\mapping\mail_sorting_helpers.dm"
#include "code\modules\mapping\map_template.dm"
@@ -5221,6 +5225,7 @@
#include "code\modules\surgery\coronary_bypass.dm"
#include "code\modules\surgery\dental_implant.dm"
#include "code\modules\surgery\ear_surgery.dm"
+#include "code\modules\surgery\experimental_dissection.dm"
#include "code\modules\surgery\eye_surgery.dm"
#include "code\modules\surgery\gastrectomy.dm"
#include "code\modules\surgery\healing.dm"