Skip to content

Commit

Permalink
Merge pull request #854 from Absolucy/surgery-thingymajig
Browse files Browse the repository at this point in the history
Serverlink implant + traitor variant!
  • Loading branch information
dwasint authored Feb 3, 2024
2 parents 75a6e0d + cbb91df commit a89b0b4
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 9 deletions.
2 changes: 1 addition & 1 deletion code/__DEFINES/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_SPINNING_WEB_TURF "spinning_web_turf"
#define TRAIT_ABDUCTOR_TRAINING "abductor-training"
#define TRAIT_ABDUCTOR_SCIENTIST_TRAINING "abductor-scientist-training"
#define TRAIT_SURGEON "surgeon"
//#define TRAIT_SURGEON "surgeon" // monke edit: replace with TRAIT_ALL_SURGERIES and TRAIT_PERFECT_SURGEON
#define TRAIT_STRONG_GRABBER "strong_grabber"
#define TRAIT_SOOTHED_THROAT "soothed-throat"
#define TRAIT_BOOZE_SLIDER "booze-slider"
Expand Down
2 changes: 2 additions & 0 deletions code/__DEFINES/~monkestation/DNA.dm
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
#define SPECIES_GOLEM_CLOCKWORK "clock_golem"

#define ORGAN_SLOT_BRAIN_SURGICAL_IMPLANT "brain_surgical"
5 changes: 4 additions & 1 deletion code/__DEFINES/~monkestation/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#define TRAIT_NO_SLAB_INVOKE "no_slab_invoke"
/// Indicates that they've inhaled helium.
#define TRAIT_HELIUM "helium"

/// Allows the user to start any surgery, anywhere. Mostly used by abductor scientists.
#define TRAIT_ALL_SURGERIES "all_surgeries"
/// Prevents the user from ever (unintentionally) failing a surgery step, and ensures they always have the maximum surgery speed.
#define TRAIT_PERFECT_SURGEON "perfect_surgeon"
/// Station trait for when the clown has bridge access *shudders*
#define STATION_TRAIT_CLOWN_BRIDGE "clown_bridge"
3 changes: 2 additions & 1 deletion code/_globalvars/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_THERMAL_VISION" = TRAIT_THERMAL_VISION,
"TRAIT_ABDUCTOR_TRAINING" = TRAIT_ABDUCTOR_TRAINING,
"TRAIT_ABDUCTOR_SCIENTIST_TRAINING" = TRAIT_ABDUCTOR_SCIENTIST_TRAINING,
"TRAIT_SURGEON" = TRAIT_SURGEON,
"TRAIT_ALL_SURGERIES" = TRAIT_ALL_SURGERIES, // monke edit: TRAIT_ALL_SURGERIES
"TRAIT_PERFECT_SURGEON" = TRAIT_PERFECT_SURGEON, // monke edit: TRAIT_PERFECT_SURGEON
"TRAIT_STRONG_GRABBER" = TRAIT_STRONG_GRABBER,
"TRAIT_SOOTHED_THROAT" = TRAIT_SOOTHED_THROAT,
"TRAIT_BOOZE_SLIDER" = TRAIT_BOOZE_SLIDER,
Expand Down
4 changes: 2 additions & 2 deletions code/modules/antagonists/abductor/abductor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@
break

/datum/antagonist/abductor/scientist/on_gain()
owner.add_traits(list(TRAIT_ABDUCTOR_SCIENTIST_TRAINING, TRAIT_SURGEON), ABDUCTOR_ANTAGONIST)
owner.add_traits(list(TRAIT_ABDUCTOR_SCIENTIST_TRAINING, TRAIT_ALL_SURGERIES), ABDUCTOR_ANTAGONIST) // monke edit: TRAIT_ALL_SURGERIES
return ..()

/datum/antagonist/abductor/scientist/on_removal()
owner.remove_traits(list(TRAIT_ABDUCTOR_SCIENTIST_TRAINING, TRAIT_SURGEON), ABDUCTOR_ANTAGONIST)
owner.remove_traits(list(TRAIT_ABDUCTOR_SCIENTIST_TRAINING, TRAIT_ALL_SURGERIES), ABDUCTOR_ANTAGONIST) // monke edit: TRAIT_ALL_SURGERIES
return ..()

/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/surgery/surgery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
return FALSE

// True surgeons (like abductor scientists) need no instructions
if(HAS_TRAIT(user, TRAIT_SURGEON) || (!isnull(user.mind) && HAS_TRAIT(user.mind, TRAIT_SURGEON)))
if(HAS_TRAIT(user, TRAIT_ALL_SURGERIES) || (!isnull(user.mind) && HAS_TRAIT(user.mind, TRAIT_ALL_SURGERIES))) // monke edit: TRAIT_ALL_SURGERIES
if(replaced_by) // only show top-level surgeries
return FALSE
else
Expand Down
8 changes: 5 additions & 3 deletions code/modules/surgery/surgery_step.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
if(!tool)
success = TRUE
if(iscyborg(user))
success = TRUE
success = TRUE

if(accept_any_item)
if(tool && tool_check(user, tool))
Expand Down Expand Up @@ -96,13 +96,15 @@

if(iscyborg(user))//any immunities to surgery slowdown should go in this check.
modded_time = time
else if(HAS_TRAIT(user, TRAIT_PERFECT_SURGEON))
modded_time = min(round(time * 0.75, 5), modded_time) // monke edit: perfect surgeon will always be at least 25% faster than normal

var/was_sleeping = (target.stat != DEAD && target.IsSleeping())

if(do_after(user, modded_time, target = target, interaction_key = user.has_status_effect(/datum/status_effect/hippocratic_oath) ? target : DOAFTER_SOURCE_SURGERY)) //If we have the hippocratic oath, we can perform one surgery on each target, otherwise we can only do one surgery in total.
if(do_after(user, modded_time, target = target, interaction_key = HAS_TRAIT(user, TRAIT_PERFECT_SURGEON) ? target : DOAFTER_SOURCE_SURGERY)) //If we have perfect surgery, we can perform one surgery on each target, otherwise we can only do one surgery in total.

var/chem_check_result = chem_check(target)
if((prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && chem_check_result && !try_to_fail)
if((HAS_TRAIT(user, TRAIT_PERFECT_SURGEON) || prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && chem_check_result && !try_to_fail) // monke edit: TRAIT_PERFECT_SURGEON

if(success(user, target, target_zone, tool, surgery))
play_success_sound(user, target, target_zone, tool, surgery)
Expand Down
7 changes: 7 additions & 0 deletions monkestation/code/datums/status_effects/buffs.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/datum/status_effect/hippocratic_oath/on_apply()
. = ..()
ADD_TRAIT(owner, TRAIT_PERFECT_SURGEON, HIPPOCRATIC_OATH_TRAIT)

/datum/status_effect/hippocratic_oath/on_remove()
. = ..()
REMOVE_TRAIT(owner, TRAIT_PERFECT_SURGEON, HIPPOCRATIC_OATH_TRAIT)
7 changes: 7 additions & 0 deletions monkestation/code/modules/cargo/packs/medical.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/datum/supply_pack/medical/serverlink_implant
name = "Serverlink Implant Set"
desc = "A crate containing two implants, which can be surgically implanted to download advanced surgical knowledge into the user's brain."
cost = CARGO_CRATE_VALUE * 8
access = ACCESS_SURGERY
contains = list(/obj/item/organ/internal/cyberimp/brain/linked_surgery = 2)
crate_name = "serverlink implant crate"
13 changes: 13 additions & 0 deletions monkestation/code/modules/research/designs/medical_designs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,16 @@
RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_MEDICAL
)
departmental_flags = DEPARTMENT_BITFLAG_MEDICAL

/datum/design/linked_surgery
name = "surgical serverlink brain implant"
desc = "A brain implant with a bluespace technology that lets you perform an advanced surgery through your station research server."
id = "linked_surgery"
build_path = /obj/item/organ/internal/cyberimp/brain/linked_surgery
build_type = PROTOLATHE | AWAY_LATHE | MECHFAB
materials = list(/datum/material/iron = 600, /datum/material/glass = 600, /datum/material/silver = 500, /datum/material/gold = 1000, /datum/material/bluespace = 250)
construction_time = 6 SECONDS
category = list(
RND_CATEGORY_CYBERNETICS + RND_SUBCATEGORY_CYBERNETICS_IMPLANTS_UTILITY
)
departmental_flags = DEPARTMENT_BITFLAG_MEDICAL
11 changes: 11 additions & 0 deletions monkestation/code/modules/research/techweb/all_nodes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,14 @@
"mag_autorifle_ic",
)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)

/datum/techweb_node/linked_surgery
id = "linked_surgery"
display_name = "Surgical Serverlink Brain Implant"
description = "A bluespace implant which a holder can read surgical programs from their server with."
prereq_ids = list("exp_surgery", "micro_bluespace")
design_ids = list("linked_surgery")
boost_item_paths = list(/obj/item/organ/internal/cyberimp/brain/linked_surgery)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
hidden = TRUE
experimental = TRUE
126 changes: 126 additions & 0 deletions monkestation/code/modules/surgery/organs/augments.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,129 @@
desc = "An internal power cord hooked up to a battery. Useful if you run on volts."
contents = newlist(/obj/item/apc_powercord)
zone = "l_arm"

/obj/item/organ/internal/cyberimp/brain/linked_surgery
name = "surgical serverlink brain implant"
desc = "A brain implant with a bluespace technology that lets you perform an advanced surgery through your station research server."
slot = ORGAN_SLOT_BRAIN_SURGICAL_IMPLANT
actions_types = list(/datum/action/item_action/organ_action/toggle)
var/list/loaded_surgeries = list()
var/static/datum/techweb/linked_techweb

/obj/item/organ/internal/cyberimp/brain/linked_surgery/Initialize()
. = ..()
if(isnull(linked_techweb))
linked_techweb = SSresearch.science_tech

/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/on_step_completion(mob/living/user, datum/surgery_step/current_step, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
SIGNAL_HANDLER
if(CHECK_BITFIELD(organ_flags, ORGAN_FAILING))
return
var/possible_steps = list()
if(current_step.repeatable)
possible_steps += "[current_step.name]"
var/datum/surgery_step/next_step = surgery.get_surgery_next_step()
if(!isnull(next_step))
possible_steps += "[next_step.name]"
qdel(next_step)
if(length(possible_steps))
target.balloon_alert(owner, "next step: [english_list(possible_steps, and_text = " or ")]")
else
target.balloon_alert(owner, "surgery done!")


/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/check_surgery(mob/user, datum/surgery/surgery, mob/patient)
SIGNAL_HANDLER
if(CHECK_BITFIELD(organ_flags, ORGAN_FAILING))
return
if(surgery.replaced_by in loaded_surgeries)
return COMPONENT_CANCEL_SURGERY
if(surgery.type in loaded_surgeries)
return COMPONENT_FORCE_SURGERY

/obj/item/organ/internal/cyberimp/brain/linked_surgery/on_insert(mob/living/carbon/organ_owner, special)
. = ..()
update_surgeries(download_from_held = FALSE, silent = TRUE)
RegisterSignal(organ_owner, COMSIG_SURGERY_STARTING, PROC_REF(check_surgery))
RegisterSignal(organ_owner, COMSIG_MOB_SURGERY_STEP_SUCCESS, PROC_REF(on_step_completion))

/obj/item/organ/internal/cyberimp/brain/linked_surgery/on_remove(mob/living/carbon/organ_owner, special)
. = ..()
UnregisterSignal(organ_owner, list(COMSIG_SURGERY_STARTING, COMSIG_MOB_SURGERY_STEP_SUCCESS))

/obj/item/organ/internal/cyberimp/brain/linked_surgery/ui_action_click(mob/user, actiontype)
if(CHECK_BITFIELD(organ_flags, ORGAN_FAILING))
to_chat(user, span_warning("\The [src] does not respond!"))
return
update_surgeries()

/obj/item/organ/internal/cyberimp/brain/linked_surgery/proc/update_surgeries(download_from_held = TRUE, silent = FALSE)
var/list/prev_amt = length(loaded_surgeries)
for(var/design in linked_techweb.researched_designs)
var/datum/design/surgery/surgery_design = SSresearch.techweb_design_by_id(design)
if(!istype(surgery_design))
continue
loaded_surgeries |= surgery_design.surgery
if(download_from_held)
for(var/held_item in owner.held_items)
if(!held_item)
continue
var/list/surgeries_to_add = list()
if(istype(held_item, /obj/item/disk/surgery))
var/obj/item/disk/surgery/surgery_disk = held_item
for(var/surgery in surgery_disk.surgeries)
surgeries_to_add |= surgery
else if(istype(held_item, /obj/item/disk/tech_disk))
var/obj/item/disk/tech_disk/tech_disk = held_item
for(var/design in tech_disk.stored_research.researched_designs)
var/datum/design/surgery/surgery_design = SSresearch.techweb_design_by_id(design)
if(!istype(surgery_design))
continue
surgeries_to_add |= surgery_design.surgery
else if(istype(held_item, /obj/item/disk/nuclear))
// funny joke message
if(!silent)
to_chat(owner, span_warning("Do you <i>want</i> to explode? You can't get surgery data from \the [held_item]!"))
continue
else
continue
if(!length(surgeries_to_add))
owner.balloon_alert(owner, "no new surgery data found")
continue
owner.balloon_alert(owner, "downloading surgery data...")
if(!do_after(owner, 5 SECONDS, held_item))
owner.balloon_alert(owner, "surgery download interrupted!")
return
loaded_surgeries |= surgeries_to_add
if(silent)
return
var/new_amt = length(loaded_surgeries)
var/diff = new_amt - prev_amt
if(diff)
owner.balloon_alert(owner, "installed [diff] new surgeries, [new_amt] total loaded")
else
owner.balloon_alert(owner, "no new surgery data found")

/obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect
name = "hacked surgical serverlink brain implant"
desc = "A brain implant with a bluespace technology that lets you perform any advanced surgery through hacked Nanotrasen servers."
organ_flags = ORGAN_SYNTHETIC | ORGAN_HIDDEN
organ_traits = list(TRAIT_PERFECT_SURGEON)
actions_types = null
var/list/blocked_surgeries = list(
/datum/surgery/advanced/brainwashing_sleeper,
/datum/surgery/advanced/necrotic_revival,
/datum/surgery/organ_extraction
)

/obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect/update_surgeries(download_from_held = TRUE, silent = FALSE)
loaded_surgeries.Cut()
for(var/datum/surgery/surgery as() in GLOB.surgeries_list)
if(surgery.type in blocked_surgeries)
continue
if(!length(surgery.steps))
continue
loaded_surgeries |= surgery.type

/obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect/debug
blocked_surgeries = list()
2 changes: 2 additions & 0 deletions monkestation/code/modules/surgery/organs/autosurgeon.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/obj/item/autosurgeon/syndicate/hacked_linked_surgery
starting_organ = /obj/item/organ/internal/cyberimp/brain/linked_surgery/perfect
10 changes: 10 additions & 0 deletions monkestation/code/modules/uplink/uplink_items/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,13 @@

/datum/uplink_item/role_restricted/modified_syringe_gun
surplus = 50

/datum/uplink_item/role_restricted/hacked_linked_surgery
name = "Syndicate Surgery Implant"
desc = "A powerful brain implant, capable of uploading perfect, forbidden surgical knowledge to its users mind, \
allowing them to do just about any surgery, anywhere, without making any (unintentional) mistakes. \
Comes with a syndicate autosurgeon for immediate self-application."
cost = 12
item = /obj/item/autosurgeon/syndicate/hacked_linked_surgery
restricted_roles = list(JOB_CHIEF_MEDICAL_OFFICER, JOB_MEDICAL_DOCTOR, JOB_PARAMEDIC, JOB_ROBOTICIST)
surplus = 50
3 changes: 3 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -5656,6 +5656,7 @@
#include "monkestation\code\datums\quirks\positive_quirks.dm"
#include "monkestation\code\datums\station_traits\negative_traits.dm"
#include "monkestation\code\datums\station_traits\neutral_traits.dm"
#include "monkestation\code\datums\status_effects\buffs.dm"
#include "monkestation\code\datums\status_effects\disorient.dm"
#include "monkestation\code\datums\status_effects\food_buffs.dm"
#include "monkestation\code\datums\wires\particle_accelerator.dm"
Expand Down Expand Up @@ -6025,6 +6026,7 @@
#include "monkestation\code\modules\cargo\crates\security.dm"
#include "monkestation\code\modules\cargo\crates\service.dm"
#include "monkestation\code\modules\cargo\markets\market_items.dm"
#include "monkestation\code\modules\cargo\packs\medical.dm"
#include "monkestation\code\modules\cargoborg\code\cargo_module.dm"
#include "monkestation\code\modules\cargoborg\code\cargo_teleporter.dm"
#include "monkestation\code\modules\cargoborg\code\cargoborg_items.dm"
Expand Down Expand Up @@ -6604,6 +6606,7 @@
#include "monkestation\code\modules\surgery\bodyparts\oozeling_bodyparts.dm"
#include "monkestation\code\modules\surgery\bodyparts\simian_bodyparts.dm"
#include "monkestation\code\modules\surgery\organs\augments.dm"
#include "monkestation\code\modules\surgery\organs\autosurgeon.dm"
#include "monkestation\code\modules\surgery\organs\external\anime.dm"
#include "monkestation\code\modules\surgery\organs\external\floran_accessories.dm"
#include "monkestation\code\modules\surgery\organs\external\goblin_accessories.dm"
Expand Down

0 comments on commit a89b0b4

Please sign in to comment.