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"