mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-19 03:55:11 +01:00
Replace slime extract experiments, required for biotech, with dissection surgery (#63033)
About The Pull Request Adds back dissection surgery for the purposes of performing experiments. Replaces the existing slime extract fetch quests with dissection surgery for biotech, and adds xenomorph dissection as an extra discount (though I would like to see a node require it some day). Why It's Good For The Game Science has no incentive to actually scan slime extracts for biotech, as the primary consumer is medical. In practice, this means that the grey slime extract experiment, which can be done round-start, is frequently left unperformed. This lets medical have some level of control over their research, while still leaving the actual act of researching the node into the hands of the science department, or heads of staff. Changelog cl add: Added back dissection surgery, which can be used with an operating computer to perform experiments for research. add: Biological technology's requirement has been changed from scanning one grey slime extract to performing a dissection surgery. add: Advanced biotech's requirement has been changed from scanning three slime extracts to performing a dissection surgery on a nonhuman. add: Xeno-organ biology and Alien Biological Tools' now have additional discounts for performing a dissection surgery on a xenomorph. /cl
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
// /obj/machinery/computer/operating signals
|
||||
|
||||
/// Fired when a dissection surgery completes.
|
||||
/// (mob/living/target)
|
||||
#define COMSIG_OPERATING_COMPUTER_DISSECTION_COMPLETE "operating_computer_dissection_complete"
|
||||
@@ -13,16 +13,30 @@
|
||||
var/datum/techweb/linked_techweb
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
var/datum/component/experiment_handler/experiment_handler
|
||||
|
||||
/obj/machinery/computer/operating/Initialize(mapload)
|
||||
. = ..()
|
||||
..()
|
||||
linked_techweb = SSresearch.science_tech
|
||||
find_table()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/operating/LateInitialize()
|
||||
. = ..()
|
||||
|
||||
experiment_handler = AddComponent( \
|
||||
/datum/component/experiment_handler, \
|
||||
allowed_experiments = list(/datum/experiment/dissection), \
|
||||
config_flags = EXPERIMENT_CONFIG_ALWAYS_ACTIVE, \
|
||||
config_mode = EXPERIMENT_CONFIG_ALTCLICK, \
|
||||
)
|
||||
|
||||
/obj/machinery/computer/operating/Destroy()
|
||||
for(var/direction in GLOB.alldirs)
|
||||
table = locate(/obj/structure/table/optable) in get_step(src, direction)
|
||||
if(table && table.computer == src)
|
||||
table.computer = null
|
||||
QDEL_NULL(experiment_handler)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params)
|
||||
@@ -134,8 +148,9 @@
|
||||
switch(action)
|
||||
if("sync")
|
||||
sync_surgeries()
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
if("open_experiments")
|
||||
experiment_handler.ui_interact(usr)
|
||||
return TRUE
|
||||
|
||||
#undef MENU_OPERATION
|
||||
#undef MENU_SURGERIES
|
||||
|
||||
@@ -2,29 +2,6 @@
|
||||
name = "Base Slime Experiment"
|
||||
required_points = 1
|
||||
|
||||
/datum/experiment/scanning/points/slime/calibration
|
||||
name = "Slime Sample Test"
|
||||
description = "Let's see if our scanners can pick up the genetic data from a simple slime extract."
|
||||
required_atoms = list(/obj/item/slime_extract/grey = 1)
|
||||
|
||||
/datum/experiment/scanning/points/slime/easy
|
||||
name = "Easy Slime Survey"
|
||||
description = "A wealthy client has requested that we provide samples of data from several basic slime cores."
|
||||
required_points = 3
|
||||
required_atoms = list(/obj/item/slime_extract/orange = 1,
|
||||
/obj/item/slime_extract/purple = 1,
|
||||
/obj/item/slime_extract/blue = 1,
|
||||
/obj/item/slime_extract/metal = 1)
|
||||
|
||||
/datum/experiment/scanning/points/slime/moderate
|
||||
name = "Moderate Slime Survey"
|
||||
description = "Central Command has asked that you collect data from several common slime cores."
|
||||
required_points = 5
|
||||
required_atoms = list(/obj/item/slime_extract/yellow = 1,
|
||||
/obj/item/slime_extract/darkpurple = 1,
|
||||
/obj/item/slime_extract/darkblue = 1,
|
||||
/obj/item/slime_extract/silver = 1)
|
||||
|
||||
/datum/experiment/scanning/points/slime/hard
|
||||
name = "Challenging Slime Survey"
|
||||
description = "Another station has challenged your research team to collect several challenging slime cores, \
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
RegisterSignal(parent, COMSIG_DOPPLER_ARRAY_EXPLOSION_DETECTED, .proc/try_run_doppler_experiment)
|
||||
if(istype(parent, /obj/machinery/destructive_scanner))
|
||||
RegisterSignal(parent, COMSIG_MACHINERY_DESTRUCTIVE_SCAN, .proc/try_run_destructive_experiment)
|
||||
if(istype(parent, /obj/machinery/computer/operating))
|
||||
RegisterSignal(parent, COMSIG_OPERATING_COMPUTER_DISSECTION_COMPLETE, .proc/try_run_dissection_experiment)
|
||||
|
||||
// Determine UI display mode
|
||||
switch(config_mode)
|
||||
@@ -173,6 +175,16 @@
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 25)
|
||||
our_array.say("Insufficient explosion to contribute to current experiment.")
|
||||
|
||||
/// Hooks on a successful dissection experiment
|
||||
/datum/component/experiment_handler/proc/try_run_dissection_experiment(obj/source, mob/living/target)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (action_experiment(source, target))
|
||||
playsound(source, 'sound/machines/ping.ogg', 25)
|
||||
else
|
||||
playsound(source, 'sound/machines/buzz-sigh.ogg', 25)
|
||||
source.say("The dissection did not result in anything, either prior dissections have not been complete, or this one has already been researched.")
|
||||
|
||||
/**
|
||||
* Announces a message to all experiment handlers
|
||||
*
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/datum/experiment/dissection
|
||||
name = "Dissection Experiment"
|
||||
description = "An experiment requiring a dissection surgery to progress"
|
||||
exp_tag = "Dissection"
|
||||
performance_hint = "Perform a dissection surgery while connected to an operating computer."
|
||||
|
||||
/datum/experiment/dissection/is_complete()
|
||||
return completed
|
||||
|
||||
/datum/experiment/dissection/perform_experiment_actions(datum/component/experiment_handler/experiment_handler, mob/target)
|
||||
if (is_valid_dissection(target))
|
||||
completed = TRUE
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/datum/experiment/dissection/proc/is_valid_dissection(mob/target)
|
||||
return TRUE
|
||||
|
||||
/datum/experiment/dissection/human
|
||||
name = "Human Dissection Experiment"
|
||||
description = "We don't want to invest in a station that doesn't know their coccyx from their cochlea. Send us back data dissecting a human to receive more funding."
|
||||
|
||||
/datum/experiment/dissection/human/is_valid_dissection(mob/target)
|
||||
return ishumanbasic(target)
|
||||
|
||||
/datum/experiment/dissection/nonhuman
|
||||
name = "Non-human Dissection Experiment"
|
||||
description = "When we asked for a tail bone, we didn't mean...look, just send us back data from something OTHER than a human. It could be a monkey for all we care, just send us research."
|
||||
|
||||
/datum/experiment/dissection/nonhuman/is_valid_dissection(mob/target)
|
||||
return ishuman(target) && !ishumanbasic(target)
|
||||
|
||||
/datum/experiment/dissection/xenomorph
|
||||
name = "Xenomorph Dissection Experiment"
|
||||
description = "Our understanding of the xenomorph only scratches the surface. Send us research from dissecting a xenomorph."
|
||||
|
||||
/datum/experiment/dissection/xenomorph/is_valid_dissection(mob/target)
|
||||
return isalien(target)
|
||||
@@ -502,15 +502,6 @@
|
||||
* I wish examine was less copypasted. (oranges say, be the change you want to see buddy)
|
||||
*/
|
||||
/mob/proc/common_trait_examine()
|
||||
if(HAS_TRAIT(src, TRAIT_DISSECTED))
|
||||
var/dissectionmsg = ""
|
||||
if(HAS_TRAIT_FROM(src, TRAIT_DISSECTED,"Extraterrestrial Dissection"))
|
||||
dissectionmsg = " via Extraterrestrial Dissection. It is no longer worth experimenting on"
|
||||
else if(HAS_TRAIT_FROM(src, TRAIT_DISSECTED,"Experimental Dissection"))
|
||||
dissectionmsg = " via Experimental Dissection"
|
||||
else if(HAS_TRAIT_FROM(src, TRAIT_DISSECTED,"Thorough Dissection"))
|
||||
dissectionmsg = " via Thorough Dissection"
|
||||
. += "[span_notice("This body has been dissected and analyzed[dissectionmsg].")]<br>"
|
||||
if(HAS_TRAIT(src,TRAIT_HUSK))
|
||||
. += span_warning("This body has been reduced to a grotesque husk.")
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
"soda_dispenser",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
required_experiments = list(/datum/experiment/scanning/points/slime/calibration)
|
||||
required_experiments = list(/datum/experiment/dissection/human)
|
||||
|
||||
/datum/techweb_node/adv_biotech
|
||||
id = "adv_biotech"
|
||||
@@ -312,7 +312,7 @@
|
||||
"smoke_machine",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
required_experiments = list(/datum/experiment/scanning/points/slime/easy)
|
||||
required_experiments = list(/datum/experiment/dissection/nonhuman)
|
||||
discount_experiments = list(/datum/experiment/scanning/random/material/meat = 4000) //Big discount to reinforce doing it.
|
||||
|
||||
/datum/techweb_node/xenoorgan_biotech
|
||||
@@ -327,7 +327,11 @@
|
||||
"limbdesign_plasmaman",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6500)
|
||||
discount_experiments = list(/datum/experiment/scanning/random/cytology/easy = 1000, /datum/experiment/scanning/points/slime/expert = 5000)
|
||||
discount_experiments = list(
|
||||
/datum/experiment/scanning/random/cytology/easy = 1000,
|
||||
/datum/experiment/scanning/points/slime/hard = 5000,
|
||||
/datum/experiment/dissection/xenomorph = 5000,
|
||||
)
|
||||
|
||||
/datum/techweb_node/bio_process
|
||||
id = "bio_process"
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/datum/surgery/dissection
|
||||
name = "Dissection"
|
||||
target_mobtypes = list(
|
||||
/mob/living/carbon/human,
|
||||
/mob/living/carbon/alien,
|
||||
)
|
||||
possible_locs = list(BODY_ZONE_CHEST)
|
||||
requires_real_bodypart = TRUE
|
||||
steps = list(
|
||||
/datum/surgery_step/incise,
|
||||
/datum/surgery_step/retract_skin,
|
||||
/datum/surgery_step/clamp_bleeders,
|
||||
/datum/surgery_step/dissection,
|
||||
/datum/surgery_step/close,
|
||||
)
|
||||
|
||||
/datum/surgery/dissection/can_start(mob/user, mob/living/patient)
|
||||
. = ..()
|
||||
|
||||
// This isn't a real advanced tech, but it doesn't make sense using it without an operating computer
|
||||
if (isnull(locate_operating_computer(get_turf(patient))))
|
||||
return FALSE
|
||||
|
||||
if (HAS_TRAIT(patient, TRAIT_DISSECTED))
|
||||
return FALSE
|
||||
|
||||
if (patient.stat != DEAD)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/surgery_step/dissection
|
||||
name = "dissect"
|
||||
time = 16 SECONDS
|
||||
implements = list(
|
||||
TOOL_SCALPEL = 100,
|
||||
/obj/item/melee/energy/sword = 75,
|
||||
/obj/item/knife = 65,
|
||||
/obj/item/shard = 45,
|
||||
/obj/item = 30,
|
||||
)
|
||||
|
||||
/datum/surgery_step/dissection/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
var/ending = "..."
|
||||
if (isnull(surgery.locate_operating_computer(get_turf(target))))
|
||||
ending = "<b>, but without a linked operating computer, you won't get any research!</b>"
|
||||
|
||||
display_results(
|
||||
user,
|
||||
target,
|
||||
span_notice("You start to dissect [target][ending]"),
|
||||
span_notice("[user] starts to dissect [target]..."),
|
||||
span_notice("[user] begins to start poking around inside your corpse...hey, wait a minute!"),
|
||||
)
|
||||
|
||||
/datum/surgery_step/dissection/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
|
||||
ADD_TRAIT(target, TRAIT_DISSECTED, REF(src))
|
||||
|
||||
var/obj/machinery/computer/operating/operating_computer = surgery.locate_operating_computer(get_turf(target))
|
||||
if (!isnull(operating_computer))
|
||||
SEND_SIGNAL(operating_computer, COMSIG_OPERATING_COMPUTER_DISSECTION_COMPLETE, target)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/surgery_step/dissection/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, fail_prob)
|
||||
display_results(
|
||||
user,
|
||||
target,
|
||||
span_notice("You mess up, damaging some of the internal organs!"),
|
||||
span_notice("[user] messes up, damaging some of the internal organs!"),
|
||||
span_notice("[user] messes up, damaging some of your internal organs!")
|
||||
)
|
||||
|
||||
target.adjustOrganLoss(pick(
|
||||
ORGAN_SLOT_APPENDIX,
|
||||
ORGAN_SLOT_BRAIN,
|
||||
ORGAN_SLOT_HEART,
|
||||
ORGAN_SLOT_LIVER,
|
||||
ORGAN_SLOT_LUNGS,
|
||||
ORGAN_SLOT_STOMACH,
|
||||
), 20)
|
||||
|
||||
return FALSE
|
||||
|
||||
/datum/surgery_step/dissection/tool_check(mob/user, obj/item/tool)
|
||||
return implement_type != /obj/item || tool.get_sharpness() > 0
|
||||
@@ -76,14 +76,9 @@
|
||||
var/turf/patient_turf = get_turf(patient)
|
||||
|
||||
//Get the relevant operating computer
|
||||
var/obj/machinery/computer/operating/opcomputer
|
||||
var/obj/structure/table/optable/optable = locate(/obj/structure/table/optable, patient_turf)
|
||||
if(optable?.computer)
|
||||
opcomputer = optable.computer
|
||||
if(!opcomputer)
|
||||
return
|
||||
if(opcomputer.machine_stat & (NOPOWER|BROKEN))
|
||||
return .
|
||||
var/obj/machinery/computer/operating/opcomputer = locate_operating_computer(patient_turf)
|
||||
if (isnull(opcomputer))
|
||||
return FALSE
|
||||
if(replaced_by in opcomputer.advanced_surgeries)
|
||||
return FALSE
|
||||
if(type in opcomputer.advanced_surgeries)
|
||||
@@ -133,6 +128,22 @@
|
||||
)
|
||||
qdel(src)
|
||||
|
||||
/// Returns a nearby operating computer linked to an operating table
|
||||
/datum/surgery/proc/locate_operating_computer(turf/patient_turf)
|
||||
if (isnull(patient_turf))
|
||||
return null
|
||||
|
||||
var/obj/structure/table/optable/operating_table = locate(/obj/structure/table/optable, patient_turf)
|
||||
var/obj/machinery/computer/operating/operating_computer = operating_table?.computer
|
||||
|
||||
if (isnull(operating_computer))
|
||||
return null
|
||||
|
||||
if(operating_computer.machine_stat & (NOPOWER|BROKEN))
|
||||
return null
|
||||
|
||||
return operating_computer
|
||||
|
||||
/datum/surgery/advanced
|
||||
name = "advanced surgery"
|
||||
requires_tech = TRUE
|
||||
|
||||
@@ -197,6 +197,7 @@
|
||||
#include "code\__DEFINES\dcs\signals\signals_music.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_NTNet.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_object.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_operating_computer.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_radiation.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_reagent.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_restaurant.dm"
|
||||
@@ -2499,6 +2500,7 @@
|
||||
#include "code\modules\experisci\experiment\experiments.dm"
|
||||
#include "code\modules\experisci\experiment\physical_experiments.dm"
|
||||
#include "code\modules\experisci\experiment\handlers\experiment_handler.dm"
|
||||
#include "code\modules\experisci\experiment\types\dissection_experiment.dm"
|
||||
#include "code\modules\experisci\experiment\types\experiment.dm"
|
||||
#include "code\modules\experisci\experiment\types\exploration.dm"
|
||||
#include "code\modules\experisci\experiment\types\explosive.dm"
|
||||
@@ -3754,6 +3756,7 @@
|
||||
#include "code\modules\surgery\core_removal.dm"
|
||||
#include "code\modules\surgery\coronary_bypass.dm"
|
||||
#include "code\modules\surgery\dental_implant.dm"
|
||||
#include "code\modules\surgery\dissection.dm"
|
||||
#include "code\modules\surgery\eye_surgery.dm"
|
||||
#include "code\modules\surgery\gastrectomy.dm"
|
||||
#include "code\modules\surgery\healing.dm"
|
||||
|
||||
@@ -22,7 +22,9 @@ const damageTypes = [
|
||||
];
|
||||
|
||||
export const OperatingComputer = (props, context) => {
|
||||
const { act } = useBackend(context);
|
||||
const [tab, setTab] = useSharedState(context, 'tab', 1);
|
||||
|
||||
return (
|
||||
<Window
|
||||
width={350}
|
||||
@@ -39,6 +41,10 @@ export const OperatingComputer = (props, context) => {
|
||||
onClick={() => setTab(2)}>
|
||||
Surgery Procedures
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
onClick={() => act("open_experiments")}>
|
||||
Experiments
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{tab === 1 && (
|
||||
<PatientStateView />
|
||||
|
||||
Reference in New Issue
Block a user