diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index a4ae6590bf..5bd0ee5b3b 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -117,7 +117,6 @@ #define BIOWARE_NERVES "nerves" #define BIOWARE_CIRCULATION "circulation" #define BIOWARE_LIGAMENTS "ligaments" -#define BIOWARE_DISSECTION "dissected" //Health hud screws for carbon mobs #define SCREWYHUD_NONE 0 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 79ba18b5d5..e22dcfbbe0 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -81,6 +81,7 @@ #define TRAIT_PUSHIMMUNE "push_immunity" #define TRAIT_SHOCKIMMUNE "shock_immunity" #define TRAIT_STABLEHEART "stable_heart" +#define TRAIT_STABLELIVER "stable_liver" #define TRAIT_RESISTHEAT "resist_heat" #define TRAIT_RESISTHEATHANDS "resist_heat_handsonly" //For when you want to be able to touch hot things, but still want fire to be an issue. #define TRAIT_RESISTCOLD "resist_cold" @@ -110,6 +111,7 @@ #define TRAIT_NOHARDCRIT "nohardcrit" #define TRAIT_NOSOFTCRIT "nosoftcrit" #define TRAIT_MINDSHIELD "mindshield" +#define TRAIT_DISSECTED "dissected" #define TRAIT_FEARLESS "fearless" #define TRAIT_UNSTABLE "unstable" #define TRAIT_PARALYSIS_L_ARM "para-l-arm" //These are used for brain-based paralysis, where replacing the limb won't fix it @@ -121,6 +123,9 @@ #define TRAIT_STRONG_GRABBER "strong_grabber" #define TRAIT_CALCIUM_HEALER "calcium_healer" #define TRAIT_CAPTAIN_METABOLISM "captain-metabolism" +#define TRAIT_ABDUCTOR_TRAINING "abductor-training" +#define TRAIT_ABDUCTOR_SCIENTIST_TRAINING "abductor-scientist-training" +#define TRAIT_SURGEON "surgeon" //non-mob traits #define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it @@ -179,6 +184,7 @@ // unique trait sources, still defines #define STATUE_MUTE "statue" +#define CLONING_POD_TRAIT "cloning-pod" #define CHANGELING_DRAIN "drain" #define CHANGELING_HIVEMIND_MUTE "ling_mute" #define ABYSSAL_GAZE_BLIND "abyssal_gaze" @@ -208,3 +214,4 @@ #define LOCKED_HELMET_TRAIT "locked-helmet" #define NINJA_SUIT_TRAIT "ninja-suit" #define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant" +#define ABDUCTOR_ANTAGONIST "abductor-antagonist" \ No newline at end of file diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 8e49c0a126..89c5e56b71 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -175,11 +175,12 @@ //Get the clone body ready maim_clone(H) - ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning") - ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning") - ADD_TRAIT(H, TRAIT_MUTE, "cloning") - ADD_TRAIT(H, TRAIT_NOBREATH, "cloning") - ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning") + ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) H.Unconscious(80) clonemind.transfer_to(H) @@ -361,11 +362,12 @@ if(!mob_occupant) return - REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, "cloning") - REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, "cloning") - REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, "cloning") - REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, "cloning") - REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, "cloning") + REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, CLONING_POD_TRAIT) if(grab_ghost_when == CLONER_MATURE_CLONE) mob_occupant.grab_ghost() diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm index b594991a7d..25e5948b51 100644 --- a/code/game/machinery/exp_cloner.dm +++ b/code/game/machinery/exp_cloner.dm @@ -42,11 +42,12 @@ icon_state = "pod_1" //Get the clone body ready maim_clone(H) - ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning") - ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning") - ADD_TRAIT(H, TRAIT_MUTE, "cloning") - ADD_TRAIT(H, TRAIT_NOBREATH, "cloning") - ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning") + ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) H.Unconscious(80) var/list/candidates = pollCandidatesForMob("Do you want and agree to play as a [clonename]'s defective clone, respect their character and not engage in ERP without permission from the original?", null, null, null, 100, H, POLL_IGNORE_CLONE) diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 0fca957ffe..80eb007605 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -44,6 +44,7 @@ owner.assigned_role = "[name] [sub_role]" owner.objectives += team.objectives finalize_abductor() + ADD_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST) return ..() /datum/antagonist/abductor/on_removal() @@ -51,6 +52,7 @@ if(owner.current) to_chat(owner.current,"You are no longer the [owner.special_role]!") owner.special_role = null + REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST) return ..() /datum/antagonist/abductor/greet() @@ -75,11 +77,15 @@ update_abductor_icons_added(owner,"abductor") -/datum/antagonist/abductor/scientist/finalize_abductor() - ..() - var/mob/living/carbon/human/H = owner.current - var/datum/species/abductor/A = H.dna.species - A.scientist = TRUE +/datum/antagonist/abductor/scientist/on_gain() + ADD_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST) + ADD_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST) + . = ..() + +/datum/antagonist/abductor/scientist/on_removal() + REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST) + REMOVE_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST) + . = ..() /datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin) var/list/current_teams = list() @@ -214,4 +220,4 @@ /datum/antagonist/proc/update_abductor_icons_removed(datum/mind/alien_mind) var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR] hud.leave_hud(alien_mind.current) - set_antag_hud(alien_mind.current, null) \ No newline at end of file + set_antag_hud(alien_mind.current, null) diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 1573204d88..7620aa752b 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -132,22 +132,24 @@ /obj/item/abductor icon = 'icons/obj/abductor.dmi' -/obj/item/abductor/proc/AbductorCheck(user) - if(isabductor(user)) +/obj/item/abductor/proc/AbductorCheck(mob/user) + if(HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING)) return TRUE to_chat(user, "You can't figure how this works!") return FALSE -/obj/item/abductor/proc/ScientistCheck(user) - if(!AbductorCheck(user)) - return FALSE +/obj/item/abductor/proc/ScientistCheck(mob/user) + var/training = HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) + var/sci_training = HAS_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) - var/mob/living/carbon/human/H = user - var/datum/species/abductor/S = H.dna.species - if(S.scientist) - return TRUE - to_chat(user, "You're not trained to use this!") - return FALSE + if(training && !sci_training) + to_chat(user, "You're not trained to use this!") + . = FALSE + else if(!training && !sci_training) + to_chat(user, "You can't figure how this works!") + . = FALSE + else + . = TRUE /obj/item/abductor/gizmo name = "science tool" @@ -683,7 +685,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} desc = "Abduct with style - spiky style. Prevents digital tracking." icon_state = "alienhelmet" item_state = "alienhelmet" - blockTracking = 1 + blockTracking = TRUE flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR // Operating Table / Beds / Lockers diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index 8e722ec33e..cc52b3e910 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -5,6 +5,7 @@ icon_state = "gland" status = ORGAN_ROBOTIC beating = TRUE + var/true_name = "baseline placebo referencer" var/cooldown_low = 300 var/cooldown_high = 300 var/next_activation = 0 @@ -16,6 +17,11 @@ var/mind_control_duration = 1800 var/active_mind_control = FALSE +/obj/item/organ/heart/gland/examine(mob/user) + . = ..() + if(HAS_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) || isobserver(user)) + to_chat(user, "It is \a [true_name].") + /obj/item/organ/heart/gland/proc/ownerCheck() if(ishuman(owner)) return TRUE @@ -95,6 +101,7 @@ return /obj/item/organ/heart/gland/heals + true_name = "coherency harmonizer" cooldown_low = 200 cooldown_high = 400 uses = -1 @@ -109,6 +116,7 @@ owner.adjustOxyLoss(-20) /obj/item/organ/heart/gland/slime + true_name = "gastric animation galvanizer" cooldown_low = 600 cooldown_high = 1200 uses = -1 @@ -130,6 +138,7 @@ Slime.Leader = owner /obj/item/organ/heart/gland/mindshock + true_name = "neural crosstalk uninhibitor" cooldown_low = 400 cooldown_high = 700 uses = -1 @@ -156,6 +165,7 @@ H.hallucination += 60 /obj/item/organ/heart/gland/pop + true_name = "anthropmorphic translocator" cooldown_low = 900 cooldown_high = 1800 uses = -1 @@ -171,6 +181,7 @@ owner.set_species(species) /obj/item/organ/heart/gland/ventcrawling + true_name = "pliant cartilage enabler" cooldown_low = 1800 cooldown_high = 2400 uses = 1 @@ -183,6 +194,7 @@ owner.ventcrawler = VENTCRAWLER_ALWAYS /obj/item/organ/heart/gland/viral + true_name = "contamination incubator" cooldown_low = 1800 cooldown_high = 2400 uses = 1 @@ -217,6 +229,7 @@ return A /obj/item/organ/heart/gland/trauma + true_name = "white matter randomiser" cooldown_low = 800 cooldown_high = 1200 uses = 5 @@ -235,6 +248,7 @@ owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY)) /obj/item/organ/heart/gland/spiderman + true_name = "araneae cloister accelerator" cooldown_low = 450 cooldown_high = 900 uses = -1 @@ -249,6 +263,7 @@ S.directive = "Protect your nest inside [owner.real_name]." /obj/item/organ/heart/gland/egg + true_name = "roe/enzymatic synthesizer" cooldown_low = 300 cooldown_high = 400 uses = -1 @@ -264,6 +279,7 @@ new /obj/item/reagent_containers/food/snacks/egg/gland(T) /obj/item/organ/heart/gland/electric + true_name = "electron accumulator/discharger" cooldown_low = 800 cooldown_high = 1200 uses = -1 @@ -289,6 +305,7 @@ playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1) /obj/item/organ/heart/gland/chem + true_name = "intrinsic pharma-provider" cooldown_low = 50 cooldown_high = 50 uses = -1 @@ -315,6 +332,7 @@ ..() /obj/item/organ/heart/gland/plasma + true_name = "effluvium sanguine-synonym emitter" cooldown_low = 1200 cooldown_high = 1800 uses = -1 diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm index 41cfa6a954..00e48cb1c7 100644 --- a/code/modules/antagonists/abductor/machinery/camera.dm +++ b/code/modules/antagonists/abductor/machinery/camera.dm @@ -55,8 +55,7 @@ actions += set_droppoint_action /obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H) - var/datum/species/abductor/S = H.dna.species - return S.scientist + return HAS_TRAIT(H, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) /datum/action/innate/teleport_in name = "Send To" diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm index 46d69ba9bb..30b82398ff 100644 --- a/code/modules/antagonists/abductor/machinery/console.dm +++ b/code/modules/antagonists/abductor/machinery/console.dm @@ -28,7 +28,7 @@ . = ..() if(.) return - if(!isabductor(user)) + if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING)) to_chat(user, "You start mashing alien buttons at random!") if(do_after(user,100, target = src)) TeleporterSend() diff --git a/code/modules/antagonists/abductor/machinery/pad.dm b/code/modules/antagonists/abductor/machinery/pad.dm index 1cb95fbf05..ab636f7d0e 100644 --- a/code/modules/antagonists/abductor/machinery/pad.dm +++ b/code/modules/antagonists/abductor/machinery/pad.dm @@ -53,4 +53,4 @@ . = ..() var/datum/effect_system/spark_spread/S = new S.set_up(10,0,loc) - S.start() \ No newline at end of file + S.start() diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 22da46346c..c029eac12b 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -91,6 +91,7 @@ if(combatmode) msg += "[t_He] [t_is] visibly tense[resting ? "." : ", and [t_is] standing in combative stance."]\n" + msg += common_trait_examine() GET_COMPONENT_FROM(mood, /datum/component/mood, src) if(mood) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 5b224444e0..6ebc4f8a32 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -335,6 +335,8 @@ if(digitalcamo) msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n" + msg += common_trait_examine() + var/traitstring = get_trait_string() if(ishuman(user)) var/mob/living/carbon/human/H = user diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index ad1f5c9190..ffd129ebf7 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -6,10 +6,6 @@ species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL) inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NOGUNS,TRAIT_NOHUNGER,TRAIT_NOBREATH) mutanttongue = /obj/item/organ/tongue/abductor - var/scientist = FALSE // vars to not pollute spieces list with castes - -/datum/species/abductor/copy_properties_from(datum/species/abductor/old_species) - scientist = old_species.scientist /datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index d1839db2cf..5b18e95235 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -702,7 +702,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put /mob/living/carbon/proc/liver_failure() reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE) - if(HAS_TRAIT(src, TRAIT_STABLEHEART)) + if(HAS_TRAIT(src, TRAIT_STABLELIVER)) return adjustToxLoss(4, TRUE, TRUE) if(prob(30)) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 5519c9be95..93b4d32123 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -486,3 +486,15 @@ It's fairly easy to fix if dealing with single letters but not so much with comp /mob/proc/can_hear() . = TRUE + +//Examine text for traits shared by multiple types. I wish examine was less copypasted. +/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" + . += "This body has been dissected and analyzed[dissectionmsg].
" \ No newline at end of file diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 951a77b0e8..255b18077d 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1297,10 +1297,12 @@ /datum/reagent/medicine/corazone/on_mob_metabolize(mob/living/M) ..() - ADD_TRAIT(M, TRAIT_STABLEHEART, id) + ADD_TRAIT(M, TRAIT_STABLEHEART, type) + ADD_TRAIT(M, TRAIT_STABLELIVER, type) /datum/reagent/medicine/corazone/on_mob_end_metabolize(mob/living/M) - REMOVE_TRAIT(M, TRAIT_STABLEHEART, id) + REMOVE_TRAIT(M, TRAIT_STABLEHEART, type) + REMOVE_TRAIT(M, TRAIT_STABLELIVER, type) ..() /datum/reagent/medicine/muscle_stimulant diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index ae01b75dd9..d8b00ddd61 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -729,12 +729,22 @@ var/surgery /datum/design/surgery/experimental_dissection - name = "Experimental Dissection" - desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database." - id = "surgery_exp_dissection" - surgery = /datum/surgery/advanced/bioware/experimental_dissection + name = "Advanced Dissection" + desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database." + id = "surgery_adv_dissection" + surgery = /datum/surgery/advanced/experimental_dissection/adv research_icon_state = "surgery_chest" +/datum/design/surgery/experimental_dissection/exp + name = "Experimental Dissection" + id = "surgery_exp_dissection" + surgery = /datum/surgery/advanced/experimental_dissection/exp + +/datum/design/surgery/experimental_dissection/ext + name = "Extraterrestrial Dissection" + id = "surgery_ext_dissection" + surgery = /datum/surgery/advanced/experimental_dissection/alien + /datum/design/surgery/lobotomy name = "Lobotomy" desc = "An invasive surgical procedure which guarantees removal of almost all brain traumas, but might cause another permanent trauma in return." @@ -805,6 +815,13 @@ surgery = /datum/surgery/advanced/bioware/vein_threading research_icon_state = "surgery_chest" +/datum/design/surgery/muscled_veins + name = "Vein Muscle Membrane" + desc = "A surgical procedure which adds a muscled membrane to blood vessels, allowing them to pump blood without a heart." + id = "surgery_muscled_veins" + surgery = /datum/surgery/advanced/bioware/muscled_veins + research_icon_state = "surgery_chest" + /datum/design/surgery/ligament_hook name = "Ligament Hook" desc = "A surgical procedure which reshapes the connections between torso and limbs, making it so limbs can be attached manually if severed. \ diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 477bfbe1a1..0c9d4ca98b 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -115,7 +115,7 @@ display_name = "Advanced Surgery" description = "When simple medicine doesn't cut it." prereq_ids = list("adv_biotech") - design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox", "surgery_exp_dissection") + design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox", "surgery_adv_dissection") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 @@ -124,7 +124,7 @@ display_name = "Experimental Surgery" description = "When evolution isn't fast enough." prereq_ids = list("adv_surgery") - design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond") + design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_muscled_veins","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) export_price = 5000 @@ -133,7 +133,7 @@ display_name = "Alien Surgery" description = "Abductors did nothing wrong." prereq_ids = list("exp_surgery", "alientech") - design_ids = list("surgery_brainwashing","surgery_zombie") + design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) export_price = 5000 diff --git a/code/modules/surgery/advanced/bioware/bioware_surgery.dm b/code/modules/surgery/advanced/bioware/bioware_surgery.dm index 86817b9b09..eb8f739193 100644 --- a/code/modules/surgery/advanced/bioware/bioware_surgery.dm +++ b/code/modules/surgery/advanced/bioware/bioware_surgery.dm @@ -5,6 +5,8 @@ /datum/surgery/advanced/bioware/can_start(mob/user, mob/living/carbon/human/target) if(!..()) return FALSE + if(!istype(target)) + return FALSE for(var/X in target.bioware) var/datum/bioware/B = X if(B.mod_type == bioware_target) diff --git a/code/modules/surgery/advanced/bioware/experimental_dissection.dm b/code/modules/surgery/advanced/bioware/experimental_dissection.dm deleted file mode 100644 index 5dac3e744d..0000000000 --- a/code/modules/surgery/advanced/bioware/experimental_dissection.dm +++ /dev/null @@ -1,72 +0,0 @@ -/datum/surgery/advanced/bioware/experimental_dissection - name = "Experimental Dissection" - desc = "A surgical procedure which deeply 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/clamp_bleeders, - /datum/surgery_step/incise, - /datum/surgery_step/dissection, - /datum/surgery_step/close) - possible_locs = list(BODY_ZONE_CHEST) - bioware_target = BIOWARE_DISSECTION - -/datum/surgery/advanced/bioware/experimental_dissection/can_start(mob/user, mob/living/carbon/target) - . = ..() - if(iscyborg(user)) - return FALSE //robots cannot be creative - //(also this surgery shouldn't be consistently successful, and cyborgs have a 100% success rate on surgery) - if(target.stat != DEAD) - return FALSE - -/datum/surgery_step/dissection - name = "dissection" - implements = list(TOOL_SCALPEL = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15) - time = 125 - -/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You start dissecting [target].", - "[user] starts dissecting [target].", - "[user] starts dissecting [target].") - -/datum/surgery_step/dissection/proc/check_value(mob/living/carbon/target) - if(isalienroyal(target)) - return 10000 - else if(isalienadult(target)) - return 5000 - else if(ismonkey(target)) - return 1000 - else if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(H.dna && H.dna.species) - if(isabductor(H)) - return 8000 - if(isgolem(H) || iszombie(H)) - return 4000 - if(isjellyperson(H) || ispodperson(H)) - return 3000 - return 2000 - -/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You dissect [target], and add your discoveries to the research database!", - "[user] dissects [target], adding [user.p_their()] discoveries to the research database!", - "[user] dissects [target]!") - SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = check_value(target))) - var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) - target.apply_damage(80, BRUTE, L) - new /datum/bioware/dissected(target) - return TRUE - -/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - display_results(user, target, "You dissect [target], but do not find anything particularly interesting.", - "[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.", - "[user] dissects [target], but looks a little dissapointed.") - SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (check_value(target) * 0.2))) - var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) - target.apply_damage(80, BRUTE, L) - new /datum/bioware/dissected(target) - return TRUE - -/datum/bioware/dissected - name = "Dissected" - desc = "This body has been dissected and analyzed. It is no longer worth experimenting on." - mod_type = BIOWARE_DISSECTION \ No newline at end of file diff --git a/code/modules/surgery/advanced/bioware/muscled_veins.dm b/code/modules/surgery/advanced/bioware/muscled_veins.dm new file mode 100644 index 0000000000..81212019a8 --- /dev/null +++ b/code/modules/surgery/advanced/bioware/muscled_veins.dm @@ -0,0 +1,42 @@ +/datum/surgery/advanced/bioware/muscled_veins + name = "Vein Muscle Membrane" + desc = "A surgical procedure which adds a muscled membrane to blood vessels, allowing them to pump blood without a heart." + steps = list(/datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/incise, + /datum/surgery_step/incise, + /datum/surgery_step/muscled_veins, + /datum/surgery_step/close) + possible_locs = list(BODY_ZONE_CHEST) + bioware_target = BIOWARE_CIRCULATION + +/datum/surgery_step/muscled_veins + name = "shape vein muscles" + accept_hand = TRUE + time = 125 + +/datum/surgery_step/muscled_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You start wrapping muscles around [target]'s circulatory system.", + "[user] starts wrapping muscles around [target]'s circulatory system.", + "[user] starts manipulating [target]'s circulatory system.") + +/datum/surgery_step/muscled_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You reshape [target]'s circulatory system, adding a muscled membrane!", + "[user] reshapes [target]'s circulatory system, adding a muscled membrane!", + "[user] finishes manipulating [target]'s circulatory system.") + new /datum/bioware/muscled_veins(target) + return TRUE + +/datum/bioware/muscled_veins + name = "Threaded Veins" + desc = "The circulatory system is woven into a mesh, severely reducing the amount of blood lost from wounds." + mod_type = BIOWARE_CIRCULATION + +/datum/bioware/muscled_veins/on_gain() + ..() + ADD_TRAIT(owner, TRAIT_STABLEHEART, "muscled_veins") + +/datum/bioware/muscled_veins/on_lose() + ..() + REMOVE_TRAIT(owner, TRAIT_STABLEHEART, "muscled_veins") \ No newline at end of file diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm index 28d2f8fe28..b067cce56b 100644 --- a/code/modules/surgery/advanced/brainwashing.dm +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -13,8 +13,9 @@ /datum/surgery_step/brainwash, /datum/surgery_step/close) - species = list(/mob/living/carbon/human) + target_mobtypes = list(/mob/living/carbon/human) possible_locs = list(BODY_ZONE_HEAD) + /datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target) if(!..()) return FALSE diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm index c8c699bfbd..5667a2132d 100644 --- a/code/modules/surgery/advanced/lobotomy.dm +++ b/code/modules/surgery/advanced/lobotomy.dm @@ -9,7 +9,7 @@ /datum/surgery_step/lobotomize, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 /datum/surgery/advanced/lobotomy/can_start(mob/user, mob/living/carbon/target) diff --git a/code/modules/surgery/advanced/pacification.dm b/code/modules/surgery/advanced/pacification.dm index 8a236709a4..866c85842b 100644 --- a/code/modules/surgery/advanced/pacification.dm +++ b/code/modules/surgery/advanced/pacification.dm @@ -7,7 +7,8 @@ /datum/surgery_step/clamp_bleeders, /datum/surgery_step/pacify, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 /datum/surgery/advanced/pacify/can_start(mob/user, mob/living/carbon/target) diff --git a/code/modules/surgery/advanced/reconstruction.dm b/code/modules/surgery/advanced/reconstruction.dm index b5369838d4..9e2fd79d96 100644 --- a/code/modules/surgery/advanced/reconstruction.dm +++ b/code/modules/surgery/advanced/reconstruction.dm @@ -11,7 +11,7 @@ /datum/surgery_step/reconstruct, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST) requires_bodypart_type = 0 diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index b31a7518bd..a2d5345ea4 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -8,7 +8,8 @@ /datum/surgery_step/incise, /datum/surgery_step/revive, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 /datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target) diff --git a/code/modules/surgery/advanced/toxichealing.dm b/code/modules/surgery/advanced/toxichealing.dm index 998ca47b45..bb28a0fb05 100644 --- a/code/modules/surgery/advanced/toxichealing.dm +++ b/code/modules/surgery/advanced/toxichealing.dm @@ -11,7 +11,7 @@ /datum/surgery_step/toxichealing, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST) requires_bodypart_type = 0 diff --git a/code/modules/surgery/advanced/viral_bonding.dm b/code/modules/surgery/advanced/viral_bonding.dm index bdfd0e1552..e6e24238c1 100644 --- a/code/modules/surgery/advanced/viral_bonding.dm +++ b/code/modules/surgery/advanced/viral_bonding.dm @@ -7,7 +7,8 @@ /datum/surgery_step/incise, /datum/surgery_step/viral_bond, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST) /datum/surgery/advanced/viral_bonding/can_start(mob/user, mob/living/carbon/target) if(!..()) diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index 59493872e2..5c77532188 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -1,7 +1,7 @@ /datum/surgery/amputation name = "Amputation" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/sever_limb) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG, BODY_ZONE_HEAD) requires_bodypart_type = 0 /datum/surgery_step/sever_limb diff --git a/code/modules/surgery/brain_surgery.dm b/code/modules/surgery/brain_surgery.dm index 63a5f8c728..d86f5731c7 100644 --- a/code/modules/surgery/brain_surgery.dm +++ b/code/modules/surgery/brain_surgery.dm @@ -7,7 +7,8 @@ /datum/surgery_step/clamp_bleeders, /datum/surgery_step/fix_brain, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_HEAD) requires_bodypart_type = 0 /datum/surgery_step/fix_brain diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index 4c65b56962..e50f8ddcac 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -1,7 +1,7 @@ /datum/surgery/cavity_implant name = "Cavity implant" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/incise, /datum/surgery_step/handle_cavity, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST) //handle cavity /datum/surgery_step/handle_cavity diff --git a/code/modules/surgery/core_removal.dm b/code/modules/surgery/core_removal.dm index 1ded00da2b..3f36a8bb8c 100644 --- a/code/modules/surgery/core_removal.dm +++ b/code/modules/surgery/core_removal.dm @@ -1,8 +1,10 @@ /datum/surgery/core_removal name = "Core removal" steps = list(/datum/surgery_step/incise, /datum/surgery_step/extract_core) - species = list(/mob/living/simple_animal/slime) + target_mobtypes = list(/mob/living/simple_animal/slime) possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) + lying_required = FALSE + ignore_clothes = TRUE /datum/surgery/core_removal/can_start(mob/user, mob/living/target) if(target.stat == DEAD) diff --git a/code/modules/surgery/embalming.dm b/code/modules/surgery/embalming.dm index e1053374c7..b07c2b3179 100644 --- a/code/modules/surgery/embalming.dm +++ b/code/modules/surgery/embalming.dm @@ -5,7 +5,7 @@ /datum/surgery_step/embalming, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST) requires_bodypart_type = 0 diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm new file mode 100644 index 0000000000..3172496146 --- /dev/null +++ b/code/modules/surgery/experimental_dissection.dm @@ -0,0 +1,113 @@ +#define BASE_HUMAN_REWARD 500 + +/datum/surgery/advanced/experimental_dissection + name = "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/clamp_bleeders, + /datum/surgery_step/dissection, + /datum/surgery_step/clamp_bleeders, + /datum/surgery_step/close) + possible_locs = list(BODY_ZONE_CHEST) + target_mobtypes = list(/mob/living) //Feel free to dissect devils but they're magic. + replaced_by = /datum/surgery/advanced/experimental_dissection/adv + requires_tech = FALSE + var/value_multiplier = 1 + +/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/target) + . = ..() + if(HAS_TRAIT_FROM(target, TRAIT_DISSECTED,"[name]")) + return FALSE + if(target.stat != DEAD) + return FALSE + +/datum/surgery_step/dissection + name = "dissection" + implements = list(/obj/item/scalpel/augment = 75, /obj/item/scalpel/advanced = 60, /obj/item/scalpel = 45, /obj/item/kitchen/knife = 20, /obj/item/shard = 10)// special tools not only cut down time but also improve probability, doesn't use TOOL_SCALPEL because different scalpels have different probs + time = 125 + silicons_obey_prob = TRUE + repeatable = TRUE + +/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You start dissecting [target].", + "[user] starts dissecting [target].", + "[user] starts dissecting [target].") + +/datum/surgery_step/dissection/proc/check_value(mob/living/target, datum/surgery/advanced/experimental_dissection/ED) + var/cost = BASE_HUMAN_REWARD + var/multi_surgery_adjust = 0 + + //determine bonus applied + if(isalienroyal(target)) + cost = (BASE_HUMAN_REWARD*10) + else if(isalienadult(target)) + cost = (BASE_HUMAN_REWARD*5) + else if(ismonkey(target)) + cost = (BASE_HUMAN_REWARD*0.5) + else if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(H?.dna?.species) + if(isabductor(H)) + cost = (BASE_HUMAN_REWARD*4) + else if(isgolem(H) || iszombie(H)) + cost = (BASE_HUMAN_REWARD*3) + /*else if(isjellyperson(H) || ispodperson(H)) CITADEL CHANGE: jelly and pod being available roundstart shouldn't give additional points + cost = (BASE_HUMAN_REWARD*2)*/ + else + cost = (BASE_HUMAN_REWARD * 0.6) + + + + //now we do math for surgeries already done (no double dipping!). + for(var/i in typesof(/datum/surgery/advanced/experimental_dissection)) + var/datum/surgery/advanced/experimental_dissection/cringe = i + if(HAS_TRAIT_FROM(target,TRAIT_DISSECTED,"[initial(cringe.name)]")) + multi_surgery_adjust = max(multi_surgery_adjust,initial(cringe.value_multiplier)) - 1 + + multi_surgery_adjust *= cost + + //multiply by multiplier in surgery + cost *= ED.value_multiplier + return (cost-multi_surgery_adjust) + +/datum/surgery_step/dissection/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/points_earned = check_value(target, surgery) + display_results(user, target, "You dissect [target], and add your [points_earned] point\s worth of discoveries to the research database!", + "[user] dissects [target], discovering [points_earned] point\s of data!", + "[user] dissects [target]!") + SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_earned)) + var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) + target.apply_damage(80, BRUTE, L) + ADD_TRAIT(target, TRAIT_DISSECTED, "[surgery.name]") + repeatable = FALSE + return TRUE + +/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results(user, target, "You dissect [target], but do not find anything particularly interesting.", + "[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.", + "[user] dissects [target], but looks a little dissapointed.") + SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (round(check_value(target, surgery) * 0.01)))) + var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) + target.apply_damage(80, BRUTE, L) + return TRUE + +/datum/surgery/advanced/experimental_dissection/adv + name = "Thorough Dissection" + value_multiplier = 2 + replaced_by = /datum/surgery/advanced/experimental_dissection/exp + requires_tech = TRUE + +/datum/surgery/advanced/experimental_dissection/exp + name = "Experimental Dissection" + value_multiplier = 5 + replaced_by = /datum/surgery/advanced/experimental_dissection/alien + requires_tech = TRUE + +/datum/surgery/advanced/experimental_dissection/alien + name = "Extraterrestrial Dissection" + value_multiplier = 10 + requires_tech = TRUE + replaced_by = null + +#undef EXPDIS_FAIL_MSG \ No newline at end of file diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm index 3e0c9c4ec3..f7a06af388 100644 --- a/code/modules/surgery/eye_surgery.dm +++ b/code/modules/surgery/eye_surgery.dm @@ -1,7 +1,7 @@ /datum/surgery/eye_surgery name = "Eye surgery" steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/fix_eyes, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_PRECISE_EYES) requires_bodypart_type = 0 //fix eyes diff --git a/code/modules/surgery/graft_synthtissue.dm b/code/modules/surgery/graft_synthtissue.dm index d9b03ca47f..7540b2cd94 100644 --- a/code/modules/surgery/graft_synthtissue.dm +++ b/code/modules/surgery/graft_synthtissue.dm @@ -4,7 +4,7 @@ /datum/surgery/graft_synthtissue name = "Graft synthtissue" - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES) steps = list( /datum/surgery_step/incise, diff --git a/code/modules/surgery/helpers.dm b/code/modules/surgery/helpers.dm index 0419a4c73f..f52bf97147 100644 --- a/code/modules/surgery/helpers.dm +++ b/code/modules/surgery/helpers.dm @@ -10,9 +10,6 @@ C = M affecting = C.get_bodypart(check_zone(selected_zone)) - if(!M.lying && !isslime(M)) //if they're prone or a slime - return - var/datum/surgery/current_surgery for(var/datum/surgery/S in M.surgeries) @@ -35,13 +32,18 @@ continue else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb continue + if(S.lying_required && !(M.lying)) + continue if(!S.can_start(user, M)) continue - for(var/path in S.species) + for(var/path in S.target_mobtypes) if(istype(M, path)) available_surgeries[S.name] = S break + if(!available_surgeries.len) + return + var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries if(P && user && user.Adjacent(M) && (I in user)) var/datum/surgery/S = available_surgeries[P] @@ -60,6 +62,8 @@ return else if(C && S.requires_bodypart) return + if(S.lying_required && !(M.lying)) + return if(!S.can_start(user, M)) return diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index c7597b6858..3eb05c91c7 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -1,7 +1,7 @@ /datum/surgery/implant_removal name = "implant removal" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/extract_implant, /datum/surgery_step/close) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST) //extract implant /datum/surgery_step/extract_implant diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index e704485da4..b1d8990b48 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -38,7 +38,7 @@ /datum/surgery/augmentation name = "Augmentation" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/replace, /datum/surgery_step/saw, /datum/surgery_step/replace_limb) - species = list(/mob/living/carbon/human) + target_mobtypes = list(/mob/living/carbon/human) possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) requires_real_bodypart = TRUE //SURGERY STEP SUCCESSES diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 42c049edd2..699b3f7f24 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -1,6 +1,6 @@ /datum/surgery/organ_manipulation - name = "Organ manipulation" - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + name = "organ manipulation" + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD) requires_real_bodypart = 1 steps = list( @@ -26,7 +26,7 @@ /datum/surgery/organ_manipulation/alien name = "Alien organ manipulation" possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) - species = list(/mob/living/carbon/alien/humanoid) + target_mobtypes = list(/mob/living/carbon/alien/humanoid) steps = list( /datum/surgery_step/saw, /datum/surgery_step/incise, diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index fdceb1fb1f..8efa40a70a 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -1,7 +1,7 @@ /datum/surgery/prosthetic_replacement name = "Prosthetic replacement" steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/add_prosthetic) - species = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) possible_locs = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG, BODY_ZONE_HEAD) requires_bodypart = FALSE //need a missing limb requires_bodypart_type = 0 diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index b013e7f252..5504d56310 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -1,155 +1,172 @@ -/datum/surgery - var/name = "surgery" - var/desc = "surgery description" - var/status = 1 - var/list/steps = list() //Steps in a surgery - var/step_in_progress = 0 //Actively performing a Surgery - var/can_cancel = 1 //Can cancel this surgery after step 1 with cautery - var/list/species = list(/mob/living/carbon/human) //Acceptable Species - var/location = BODY_ZONE_CHEST //Surgery location - var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type - var/list/possible_locs = list() //Multiple locations - var/ignore_clothes = 0 //This surgery ignores clothes - var/mob/living/carbon/target //Operation target mob - var/obj/item/bodypart/operated_bodypart //Operable body part - var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing. - var/success_multiplier = 0 //Step success propability multiplier - var/requires_real_bodypart = 0 //Some surgeries don't work on limbs that don't really exist - -/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart) - ..() - if(surgery_target) - target = surgery_target - target.surgeries += src - if(surgery_location) - location = surgery_location - if(surgery_bodypart) - operated_bodypart = surgery_bodypart - -/datum/surgery/Destroy() - if(target) - target.surgeries -= src - target = null - operated_bodypart = null - return ..() - - -/datum/surgery/proc/can_start(mob/user, mob/living/carbon/target) - // if 0 surgery wont show up in list - // put special restrictions here - return 1 - -/datum/surgery/proc/next_step(mob/user, intent) - if(step_in_progress) - return 1 - - var/try_to_fail = FALSE - if(intent == INTENT_DISARM) - try_to_fail = TRUE - - var/datum/surgery_step/S = get_surgery_step() - if(S) - var/obj/item/tool = user.get_active_held_item() - if(S.try_op(user, target, user.zone_selected, tool, src, try_to_fail)) - return TRUE - if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache - return TRUE - if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it - to_chat(user, "This step requires a different tool!") - return TRUE - -/datum/surgery/proc/get_surgery_step() - var/step_type = steps[status] - return new step_type - -/datum/surgery/proc/get_surgery_next_step() - if(status < steps.len) - var/step_type = steps[status + 1] - return new step_type - else - return null - -/datum/surgery/proc/complete() - SSblackbox.record_feedback("tally", "surgeries_completed", 1, type) - qdel(src) - -/datum/surgery/proc/get_propability_multiplier() - var/propability = 0.5 - var/turf/T = get_turf(target) - - if(locate(/obj/structure/table/optable, T)) - propability = 1 - else if(locate(/obj/structure/table, T)) - propability = 0.8 - else if(locate(/obj/structure/bed, T)) - propability = 0.7 - - return propability + success_multiplier - -/datum/surgery/advanced - name = "advanced surgery" - -/datum/surgery/advanced/can_start(mob/user, mob/living/carbon/target) - if(!..()) - return FALSE - //Abductor scientists need no instructions - if(isabductor(user)) - var/mob/living/carbon/human/H = user - var/datum/species/abductor/S = H.dna.species - if(S.scientist) - return TRUE - - if(iscyborg(user)) - var/mob/living/silicon/robot/R = user - var/obj/item/surgical_processor/SP = locate() in R.module.modules - if(!SP) - return FALSE - if(type in SP.advanced_surgeries) - return TRUE - - var/turf/T = get_turf(target) - var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T) - if(!table || !table.computer) - return FALSE - if(table.computer.stat & (NOPOWER|BROKEN)) - return FALSE - if(type in table.computer.advanced_surgeries) - return TRUE - -/obj/item/disk/surgery - name = "Surgery Procedure Disk" - desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console." - icon_state = "datadisk1" - materials = list(MAT_METAL=300, MAT_GLASS=100) - var/list/surgeries - -/obj/item/disk/surgery/debug - name = "Debug Surgery Disk" - desc = "A disk that contains all existing surgery procedures." - icon_state = "datadisk1" - materials = list(MAT_METAL=300, MAT_GLASS=100) - -/obj/item/disk/surgery/debug/Initialize() - . = ..() - surgeries = subtypesof(/datum/surgery/advanced) - -//INFO -//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand. -//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively. -//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon) -// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob. -//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets. - - -//TODO -//specific steps for some surgeries (fluff text) -//more interesting failure options -//randomised complications -//more surgeries! -//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid. -//helper for converting a zone_sel.selecting to body part (for damage) - - -//RESOLVED ISSUES //"Todo" jobs that have been completed -//combine hands/feet into the arms - Hands/feet were removed - RR -//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0 +/datum/surgery + var/name = "surgery" + var/desc = "surgery description" + var/status = 1 + var/list/steps = list() //Steps in a surgery + var/step_in_progress = 0 //Actively performing a Surgery + var/can_cancel = 1 //Can cancel this surgery after step 1 with cautery + var/list/target_mobtypes = list(/mob/living/carbon/human) //Acceptable Species + var/location = BODY_ZONE_CHEST //Surgery location + var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type + var/list/possible_locs = list() //Multiple locations + var/ignore_clothes = 0 //This surgery ignores clothes + var/mob/living/carbon/target //Operation target mob + var/obj/item/bodypart/operated_bodypart //Operable body part + var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing. + var/success_multiplier = 0 //Step success propability multiplier + var/requires_real_bodypart = 0 //Some surgeries don't work on limbs that don't really exist + var/lying_required = TRUE //Does the vicitm needs to be lying down. + var/requires_tech = FALSE + var/replaced_by + +/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart) + ..() + if(surgery_target) + target = surgery_target + target.surgeries += src + if(surgery_location) + location = surgery_location + if(surgery_bodypart) + operated_bodypart = surgery_bodypart + +/datum/surgery/Destroy() + if(target) + target.surgeries -= src + target = null + operated_bodypart = null + return ..() + + +/datum/surgery/proc/can_start(mob/user, mob/living/patient) //FALSE to not show in list + . = TRUE + if(replaced_by == /datum/surgery) + return FALSE + + if(HAS_TRAIT(user, TRAIT_SURGEON)) + if(replaced_by) + return FALSE + else + return TRUE + + if(!requires_tech && !replaced_by) + return TRUE + // True surgeons (like abductor scientists) need no instructions + + if(requires_tech) + . = FALSE + + if(iscyborg(user)) + var/mob/living/silicon/robot/R = user + var/obj/item/surgical_processor/SP = locate() in R.module.modules + if(SP) + if (replaced_by in SP.advanced_surgeries) + return FALSE + if(type in SP.advanced_surgeries) + return TRUE + + + var/turf/T = get_turf(patient) + var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T) + if(table) + if(!table.computer) + return FALSE + if(table.computer.stat & (NOPOWER|BROKEN)) + return . + if(replaced_by in table.computer.advanced_surgeries) + return FALSE + if(type in table.computer.advanced_surgeries) + return TRUE + +/datum/surgery/proc/next_step(mob/user, intent) + if(step_in_progress) + return 1 + + var/try_to_fail = FALSE + if(intent == INTENT_DISARM) + try_to_fail = TRUE + + var/datum/surgery_step/S = get_surgery_step() + if(S) + var/obj/item/tool = user.get_active_held_item() + if(S.try_op(user, target, user.zone_selected, tool, src, try_to_fail)) + return TRUE + if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache + return TRUE + if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it + to_chat(user, "This step requires a different tool!") + return TRUE + +/datum/surgery/proc/get_surgery_step() + var/step_type = steps[status] + return new step_type + +/datum/surgery/proc/get_surgery_next_step() + if(status < steps.len) + var/step_type = steps[status + 1] + return new step_type + else + return null + +/datum/surgery/proc/complete() + SSblackbox.record_feedback("tally", "surgeries_completed", 1, type) + qdel(src) + +/datum/surgery/proc/get_propability_multiplier() + var/propability = 0.5 + var/turf/T = get_turf(target) + + if(locate(/obj/structure/table/optable, T)) + propability = 1 + else if(locate(/obj/structure/table, T)) + propability = 0.8 + else if(locate(/obj/structure/bed, T)) + propability = 0.7 + + return propability + success_multiplier + +/datum/surgery/advanced + name = "advanced surgery" + requires_tech = TRUE + +/obj/item/disk/surgery + name = "Surgery Procedure Disk" + desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console." + icon_state = "datadisk1" + materials = list(MAT_METAL=300, MAT_GLASS=100) + var/list/surgeries + +/obj/item/disk/surgery/debug + name = "Debug Surgery Disk" + desc = "A disk that contains all existing surgery procedures." + icon_state = "datadisk1" + materials = list(MAT_METAL=300, MAT_GLASS=100) + +/obj/item/disk/surgery/debug/Initialize() + . = ..() + surgeries = list() + var/list/req_tech_surgeries = subtypesof(/datum/surgery) + for(var/i in req_tech_surgeries) + var/datum/surgery/beep = i + if(initial(beep.requires_tech)) + surgeries += beep + +//INFO +//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand. +//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively. +//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon) +// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob. +//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets. + + +//TODO +//specific steps for some surgeries (fluff text) +//more interesting failure options +//randomised complications +//more surgeries! +//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid. +//helper for converting a zone_sel.selecting to body part (for damage) + + +//RESOLVED ISSUES //"Todo" jobs that have been completed +//combine hands/feet into the arms - Hands/feet were removed - RR +//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0 \ No newline at end of file diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index c5a944fbb2..71f813a5b5 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -8,7 +8,9 @@ var/repeatable = FALSE //can this step be repeated? Make shure it isn't last step, or it used in surgery with `can_cancel = 1`. Or surgion will be stuck in the loop var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob. var/require_all_chems = TRUE //any on the list or all on the list? -/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + var/silicons_obey_prob = FALSE + +/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) var/success = FALSE if(accept_hand) if(!tool) @@ -46,7 +48,8 @@ else surgery.status-- return FALSE -/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + +/datum/surgery_step/proc/initiate(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) surgery.step_in_progress = TRUE var/speed_mod = 1 var/advance = FALSE @@ -60,7 +63,8 @@ if(implement_type) //this means it isn't a require hand or any item step. prob_chance = implements[implement_type] prob_chance *= surgery.get_propability_multiplier() - if((prob(prob_chance) || iscyborg(user)) && chem_check(target) && !try_to_fail) + + if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) advance = TRUE else @@ -73,19 +77,18 @@ surgery.step_in_progress = FALSE return advance - -/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You begin to perform surgery on [target]...", "[user] begins to perform surgery on [target].", "[user] begins to perform surgery on [target].") -/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You succeed.", "[user] succeeds!", "[user] finishes.") return TRUE -/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results(user, target, "You screw up!", "[user] screws up!", "[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut @@ -93,7 +96,8 @@ /datum/surgery_step/proc/tool_check(mob/user, obj/item/tool) return TRUE -/datum/surgery_step/proc/chem_check(mob/living/carbon/target) + +/datum/surgery_step/proc/chem_check(mob/living/target) if(!LAZYLEN(chems_needed)) return TRUE if(require_all_chems) diff --git a/tgstation.dme b/tgstation.dme index 983cd25754..bd7a22d503 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2781,6 +2781,7 @@ #include "code\modules\surgery\coronary_bypass.dm" #include "code\modules\surgery\dental_implant.dm" #include "code\modules\surgery\embalming.dm" +#include "code\modules\surgery\experimental_dissection.dm" #include "code\modules\surgery\eye_surgery.dm" #include "code\modules\surgery\graft_synthtissue.dm" #include "code\modules\surgery\helpers.dm" @@ -2808,9 +2809,9 @@ #include "code\modules\surgery\advanced\viral_bonding.dm" #include "code\modules\surgery\advanced\bioware\bioware.dm" #include "code\modules\surgery\advanced\bioware\bioware_surgery.dm" -#include "code\modules\surgery\advanced\bioware\experimental_dissection.dm" #include "code\modules\surgery\advanced\bioware\ligament_hook.dm" #include "code\modules\surgery\advanced\bioware\ligament_reinforcement.dm" +#include "code\modules\surgery\advanced\bioware\muscled_veins.dm" #include "code\modules\surgery\advanced\bioware\nerve_grounding.dm" #include "code\modules\surgery\advanced\bioware\nerve_splicing.dm" #include "code\modules\surgery\advanced\bioware\vein_threading.dm"