From f6f9b6f2f3eebcab3b08b52c153eef0cbfaad261 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Sat, 13 Aug 2022 02:01:39 +0200 Subject: [PATCH] [MIRROR] The Great Species Dedatumming 2: Makes external organs operable [MDB IGNORE] (#15530) * The Great Species Dedatumming 2: Makes external organs operable * Fixes merge conflicts * Partly fixes taur bodies (makes them external and use the mob sprite as their icon) Co-authored-by: Time-Green Co-authored-by: GoldenAlpharex --- code/__DEFINES/obj_flags.dm | 22 ------ code/__DEFINES/surgery.dm | 30 +++++++ .../carbon/alien/special/alien_embryo.dm | 2 +- .../carbon/human/species_types/dullahan.dm | 2 +- code/modules/surgery/advanced/brainwashing.dm | 2 +- code/modules/surgery/limb_augmentation.dm | 6 +- code/modules/surgery/organ_manipulation.dm | 73 ++++++++++++++---- .../surgery/organs/augments_internal.dm | 2 - .../organs/external/_external_organs.dm | 32 ++++++-- .../modules/surgery/organs/external/spines.dm | 4 + code/modules/surgery/organs/external/tails.dm | 2 +- code/modules/surgery/organs/external/wings.dm | 7 ++ code/modules/surgery/organs/heart.dm | 2 +- code/modules/surgery/organs/helpers.dm | 2 +- .../modules/surgery/prosthetic_replacement.dm | 10 +-- code/modules/surgery/surgery_step.dm | 2 +- icons/obj/surgery.dmi | Bin 44123 -> 45001 bytes .../sprite_accessories/taur_types.dm | 2 + tgstation.dme | 1 + 19 files changed, 140 insertions(+), 63 deletions(-) create mode 100644 code/__DEFINES/surgery.dm diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index ee68350d7b6..0ffa3856b8c 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -72,28 +72,6 @@ /// Allows for masks to use tanks on adjacentadjecent tiles. #define MASK_EXTEND_RANGE (1<<21) //SKYRAT DEFINE END -/// Flags for the organ_flags var on /obj/item/organ - -#define ORGAN_SYNTHETIC (1<<0) //Synthetic organs, or cybernetic organs. Reacts to EMPs and don't deteriorate or heal -#define ORGAN_FROZEN (1<<1) //Frozen organs, don't deteriorate -#define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed -#define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change. -#define ORGAN_VITAL (1<<4) //Currently only the brain -#define ORGAN_EDIBLE (1<<5) //is a snack? :D -#define ORGAN_SYNTHETIC_EMP (1<<6) //Synthetic organ affected by an EMP. Deteriorates over time. -#define ORGAN_UNREMOVABLE (1<<7) //Can't be removed using surgery - -DEFINE_BITFIELD(organ_flags, list( - "ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC, - "ORGAN_FROZEN" = ORGAN_FROZEN, - "ORGAN_FAILING" = ORGAN_FAILING, - "ORGAN_EXTERNAL" = ORGAN_EXTERNAL, - "ORGAN_VITAL" = ORGAN_VITAL, - "ORGAN_EDIBLE" = ORGAN_EDIBLE, - "ORGAN_SYNTHETIC_EMP" = ORGAN_SYNTHETIC_EMP, - "ORGAN_UNREMOVABLE" = ORGAN_UNREMOVABLE, -)) - /// Integrity defines for clothing (not flags but close enough) #define CLOTHING_PRISTINE 0 // We have no damage on the clothing diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm new file mode 100644 index 00000000000..64d8d522005 --- /dev/null +++ b/code/__DEFINES/surgery.dm @@ -0,0 +1,30 @@ +// Flags for the organ_flags var on /obj/item/organ +///Synthetic organs, or cybernetic organs. Reacts to EMPs and don't deteriorate or heal +#define ORGAN_SYNTHETIC (1<<0) +///Frozen organs, don't deteriorate +#define ORGAN_FROZEN (1<<1) +///Failing organs perform damaging effects until replaced or fixed +#define ORGAN_FAILING (1<<2) +///Is this organ external? defines how to manipulate the organ, should generally be reserved to cosmetic organs like tails, horns and wings +#define ORGAN_EXTERNAL (1<<3) +///Currently only the brain +#define ORGAN_VITAL (1<<4) +///is a snack? :D +#define ORGAN_EDIBLE (1<<5) +///Synthetic organ affected by an EMP. Deteriorates over time. +#define ORGAN_SYNTHETIC_EMP (1<<6) +// //Can't be removed using surgery +#define ORGAN_UNREMOVABLE (1<<7) +DEFINE_BITFIELD(organ_flags, list( + "ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC, + "ORGAN_FROZEN" = ORGAN_FROZEN, + "ORGAN_FAILING" = ORGAN_FAILING, + "ORGAN_EXTERNAL" = ORGAN_EXTERNAL, + "ORGAN_VITAL" = ORGAN_VITAL, + "ORGAN_EDIBLE" = ORGAN_EDIBLE, + "ORGAN_SYNTHETIC_EMP" = ORGAN_SYNTHETIC_EMP, + "ORGAN_UNREMOVABLE" = ORGAN_UNREMOVABLE, +)) + +/// When the surgery step fails :( +#define SURGERY_STEP_FAIL -1 diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 00049fe3930..7e77d40c0b5 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -69,7 +69,7 @@ /obj/item/organ/internal/body_egg/alien_embryo/egg_process() if(stage == 6 && prob(50)) for(var/datum/surgery/S in owner.surgeries) - if(S.location == BODY_ZONE_CHEST && istype(S.get_surgery_step(), /datum/surgery_step/manipulate_organs)) + if(S.location == BODY_ZONE_CHEST && istype(S.get_surgery_step(), /datum/surgery_step/manipulate_organs/internal)) AttemptGrow(0) return AttemptGrow() diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index 6282ebe156a..7fccf757c31 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -157,7 +157,7 @@ /obj/item/organ/internal/brain/dullahan decoy_override = TRUE - organ_flags = 0 + organ_flags = NONE /obj/item/organ/internal/tongue/dullahan zone = "abstract" diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm index 314fb1c257c..f2b4960d826 100644 --- a/code/modules/surgery/advanced/brainwashing.dm +++ b/code/modules/surgery/advanced/brainwashing.dm @@ -44,7 +44,7 @@ /datum/surgery_step/brainwash/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) objective = tgui_input_text(user, "Choose the objective to imprint on your victim's brain", "Brainwashing") if(!objective) - return -1 + return SURGERY_STEP_FAIL display_results(user, target, span_notice("You begin to brainwash [target]..."), span_notice("[user] begins to fix [target]'s brain."), span_notice("[user] begins to perform surgery on [target]'s brain.")) diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm index fbd7cbb949e..fc819a01c6f 100644 --- a/code/modules/surgery/limb_augmentation.dm +++ b/code/modules/surgery/limb_augmentation.dm @@ -16,16 +16,16 @@ /datum/surgery_step/replace_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(NOAUGMENTS in target.dna.species.species_traits) to_chat(user, span_warning("[target] cannot be augmented!")) - return -1 + return SURGERY_STEP_FAIL if(istype(tool, /obj/item/borg/apparatus/organ_storage) && istype(tool.contents[1], /obj/item/bodypart)) tool = tool.contents[1] var/obj/item/bodypart/aug = tool if(IS_ORGANIC_LIMB(aug)) to_chat(user, span_warning("That's not an augment, silly!")) - return -1 + return SURGERY_STEP_FAIL if(aug.body_zone != target_zone) to_chat(user, span_warning("[tool] isn't the right type for [parse_zone(target_zone)].")) - return -1 + return SURGERY_STEP_FAIL target_limb = surgery.operated_bodypart if(target_limb) display_results(user, target, span_notice("You begin to augment [target]'s [parse_zone(user.zone_selected)]..."), diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 676c8c74012..45ec42dbf6a 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -9,7 +9,7 @@ /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/incise, - /datum/surgery_step/manipulate_organs, //there should be bone fixing + /datum/surgery_step/manipulate_organs/internal, /datum/surgery_step/close) /datum/surgery/organ_manipulation/soft @@ -19,7 +19,7 @@ /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/incise, - /datum/surgery_step/manipulate_organs, + /datum/surgery_step/manipulate_organs/internal, /datum/surgery_step/close) /datum/surgery/organ_manipulation/alien @@ -31,7 +31,7 @@ /datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, - /datum/surgery_step/manipulate_organs, + /datum/surgery_step/manipulate_organs/internal, /datum/surgery_step/close) /datum/surgery/organ_manipulation/mechanic @@ -45,7 +45,7 @@ /datum/surgery_step/open_hatch, /datum/surgery_step/mechanic_unwrench, /datum/surgery_step/prepare_electronics, - /datum/surgery_step/manipulate_organs, + /datum/surgery_step/manipulate_organs/internal, /datum/surgery_step/mechanic_wrench, /datum/surgery_step/mechanic_close) @@ -55,11 +55,20 @@ /datum/surgery_step/mechanic_open, /datum/surgery_step/open_hatch, /datum/surgery_step/prepare_electronics, - /datum/surgery_step/manipulate_organs, + /datum/surgery_step/manipulate_organs/internal, /datum/surgery_step/mechanic_close) +/datum/surgery/organ_manipulation/external + name = "Feature manipulation" + possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/manipulate_organs/external, + /datum/surgery_step/close) + +///Organ manipulation base class. Do not use, it wont work. Use it's subtypes /datum/surgery_step/manipulate_organs - time = 64 name = "manipulate organs" repeatable = TRUE implements = list( @@ -67,6 +76,7 @@ /obj/item/borg/apparatus/organ_storage = 100) preop_sound = 'sound/surgery/organ2.ogg' success_sound = 'sound/surgery/organ1.ogg' + var/implements_extract = list(TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 55, /obj/item/kitchen/fork = 35) var/current_type var/obj/item/organ/target_organ @@ -82,13 +92,13 @@ success_sound = initial(success_sound) if(!length(tool.contents)) to_chat(user, span_warning("There is nothing inside [tool]!")) - return -1 + return SURGERY_STEP_FAIL target_organ = tool.contents[1] if(!isorgan(target_organ)) if (target_zone == BODY_ZONE_PRECISE_EYES) target_zone = check_zone(target_zone) to_chat(user, span_warning("You cannot put [target_organ] into [target]'s [parse_zone(target_zone)]!")) - return -1 + return SURGERY_STEP_FAIL tool = target_organ if(isorgan(tool)) current_type = "insert" @@ -97,11 +107,15 @@ target_organ = tool if(target_zone != target_organ.zone || target.getorganslot(target_organ.slot)) to_chat(user, span_warning("There is no room for [target_organ] in [target]'s [parse_zone(target_zone)]!")) - return -1 + return SURGERY_STEP_FAIL var/obj/item/organ/meatslab = tool if(!meatslab.useable) to_chat(user, span_warning("[target_organ] seems to have been chewed on, you can't use this!")) - return -1 + return SURGERY_STEP_FAIL + + if(!can_use_organ(user, meatslab)) + return SURGERY_STEP_FAIL + if (target_zone == BODY_ZONE_PRECISE_EYES) target_zone = check_zone(target_zone) display_results(user, target, span_notice("You begin to insert [tool] into [target]'s [parse_zone(target_zone)]..."), @@ -112,12 +126,16 @@ else if(implement_type in implements_extract) current_type = "extract" - var/list/organs = target.getorganszone(target_zone) + var/list/unfiltered_organs = target.getorganszone(target_zone) + var/list/organs = list() + for(var/organ in unfiltered_organs) + if(can_use_organ(user, organ)) + organs.Add(organ) if (target_zone == BODY_ZONE_PRECISE_EYES) target_zone = check_zone(target_zone) if(!length(organs)) to_chat(user, span_warning("There are no removable organs in [target]'s [parse_zone(target_zone)]!")) - return -1 + return SURGERY_STEP_FAIL else for(var/obj/item/organ/organ in organs) organ.on_find(user) @@ -126,22 +144,21 @@ var/chosen_organ = tgui_input_list(user, "Remove which organ?", "Surgery", sort_list(organs)) if(isnull(chosen_organ)) - return -1 + return SURGERY_STEP_FAIL target_organ = chosen_organ if(user && target && user.Adjacent(target) && user.get_active_held_item() == tool) target_organ = organs[target_organ] if(!target_organ) - return -1 + return SURGERY_STEP_FAIL if(target_organ.organ_flags & ORGAN_UNREMOVABLE) to_chat(user, span_warning("[target_organ] is too well connected to take out!")) - return -1 + return SURGERY_STEP_FAIL display_results(user, target, span_notice("You begin to extract [target_organ] from [target]'s [parse_zone(target_zone)]..."), span_notice("[user] begins to extract [target_organ] from [target]'s [parse_zone(target_zone)]."), span_notice("[user] begins to extract something from [target]'s [parse_zone(target_zone)].")) display_pain(target, "You can feel your [target_organ] being removed from your [parse_zone(target_zone)]!") else - return -1 - + return SURGERY_STEP_FAIL /datum/surgery_step/manipulate_organs/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results) if (target_zone == BODY_ZONE_PRECISE_EYES) @@ -176,3 +193,25 @@ span_notice("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!"), span_notice("[user] can't seem to extract anything from [target]'s [parse_zone(target_zone)]!")) return FALSE + +///You can never use this MUHAHAHAHAHAHAH (because its the byond version of abstract) +/datum/surgery_step/manipulate_organs/proc/can_use_organ(mob/user, obj/item/organ/organ) + return FALSE + +///Surgery step for internal organs, like hearts and brains +/datum/surgery_step/manipulate_organs/internal + time = 6.4 SECONDS + name = "manipulate organs" + +///only operate on not external organs (so internal organs) +/datum/surgery_step/manipulate_organs/internal/can_use_organ(mob/user, obj/item/organ/organ) + return !(organ.organ_flags & ORGAN_EXTERNAL) + +///Surgery step for external organs/features, like tails, frills, wings etc +/datum/surgery_step/manipulate_organs/external + time = 3.2 SECONDS + name = "manipulate features" + +///Only operate on external organs +/datum/surgery_step/manipulate_organs/external/can_use_organ(mob/user, obj/item/organ/organ) + return organ.organ_flags & ORGAN_EXTERNAL diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 989da10648b..9e711ef1d42 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -18,8 +18,6 @@ add_overlay(overlay) return ..() - - //[[[[BRAIN]]]] /obj/item/organ/internal/cyberimp/brain diff --git a/code/modules/surgery/organs/external/_external_organs.dm b/code/modules/surgery/organs/external/_external_organs.dm index 5f5f1896e8b..38ab1f5c7a3 100644 --- a/code/modules/surgery/organs/external/_external_organs.dm +++ b/code/modules/surgery/organs/external/_external_organs.dm @@ -7,8 +7,7 @@ name = "external organ" desc = "An external organ that is too external." - ///Unremovable is until the features are completely finished - organ_flags = ORGAN_UNREMOVABLE | ORGAN_EDIBLE + organ_flags = ORGAN_EXTERNAL | ORGAN_EDIBLE visual = TRUE ///Sometimes we need multiple layers, for like the back, middle and front of the person @@ -29,6 +28,8 @@ var/datum/sprite_accessory/sprite_datum ///Key of the icon states of all the sprite_datums for easy caching var/cache_key = "" + ///Set to TRUE to use the mob sprite as item sprite + var/use_mob_sprite_as_obj_sprite = FALSE ///With what DNA block do we mutate in mutate_feature() ? For genetics var/dna_block @@ -45,7 +46,6 @@ ///Does this organ have any bodytypes to pass to it's ownerlimb? var/external_bodytypes = NONE - /**mob_sprite is optional if you havent set sprite_datums for the object, and is used mostly to generate sprite_datums from a persons DNA * For _mob_sprite we make a distinction between "Round Snout" and "round". Round Snout is the name of the sprite datum, while "round" would be part of the sprite * I'm sorry @@ -152,6 +152,10 @@ var/mutable_appearance/appearance = mutable_appearance(sprite_datum.icon, finished_icon_state, layer = -image_layer) appearance.dir = image_dir + ///Also give the icon to the obj + if(use_mob_sprite_as_obj_sprite) + icon = icon(sprite_datum.icon, finished_icon_state, SOUTH) + if(sprite_datum.color_src) //There are multiple flags, but only one is ever used so meh :/ | This comment isn't true. appearance.color = draw_color @@ -242,10 +246,12 @@ /obj/item/organ/external/proc/override_color(rgb_value) CRASH("External organ color set to override with no override proc.") - ///The horns of a lizard! /obj/item/organ/external/horns name = "horns" + desc = "Why do lizards even have horns? Well, this one obviously doesn't." + icon_state = "horns" + zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_HORNS layers = EXTERNAL_ADJACENT @@ -262,6 +268,9 @@ ///The frills of a lizard (like weird fin ears) /obj/item/organ/external/frills name = "frills" + desc = "Ear-like external organs often seen on aquatic reptillians." + icon_state = "frills" + zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_FRILLS layers = EXTERNAL_ADJACENT @@ -280,7 +289,10 @@ ///Guess what part of the lizard this is? /obj/item/organ/external/snout - name = "snout" + name = "snout" // SKYRAT EDIT - ORIGINAL: name = "lizard snout" + desc = "Take a closer look at that snout!" + icon_state = "snout" + zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_SNOUT layers = EXTERNAL_ADJACENT @@ -299,7 +311,10 @@ ///A moth's antennae /obj/item/organ/external/antennae - name = "antennae" + name = "moth antennae" + desc = "A moths antennae. What is it telling them? What are they sensing?" + icon_state = "antennae" + zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_ANTENNAE layers = EXTERNAL_FRONT | EXTERNAL_BEHIND @@ -354,8 +369,11 @@ burnt = FALSE set_sprite(original_sprite) -//podperson hair +///The leafy hair of a podperson /obj/item/organ/external/pod_hair + name = "podperson hair" + desc = "Base for many-o-salads." + zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_EXTERNAL_POD_HAIR layers = EXTERNAL_FRONT|EXTERNAL_ADJACENT diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index 0667b235f72..1169bc7df96 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -1,4 +1,8 @@ /obj/item/organ/external/spines + name = "lizard spines" + desc = "Not an actual spine, obviously." + icon_state = "spines" + zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_EXTERNAL_SPINES layers = EXTERNAL_ADJACENT|EXTERNAL_BEHIND diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index f518ac9d773..713c9265f2b 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -6,7 +6,7 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_EXTERNAL_TAIL layers = EXTERNAL_FRONT|EXTERNAL_BEHIND - organ_flags = ORGAN_EDIBLE + organ_flags = ORGAN_EDIBLE | ORGAN_EXTERNAL feature_key = "tail" render_key = "tail" // dna_block = DNA_TAIL_BLOCK // SKYRAT EDIT REMOVAL - Customization - We have our own system to handle DNA. diff --git a/code/modules/surgery/organs/external/wings.dm b/code/modules/surgery/organs/external/wings.dm index 299a0ff2b3c..fa353392054 100644 --- a/code/modules/surgery/organs/external/wings.dm +++ b/code/modules/surgery/organs/external/wings.dm @@ -1,9 +1,13 @@ ///Wing base type. doesn't really do anything /obj/item/organ/external/wings + name = "wings" + desc = "Spread your wings and FLLLLLLLLYYYYY!" + zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_EXTERNAL_WINGS layers = ALL_EXTERNAL_OVERLAYS + use_mob_sprite_as_obj_sprite = TRUE feature_key = "wings" /obj/item/organ/external/wings/can_draw_on_bodypart(mob/living/carbon/human/human) @@ -164,6 +168,9 @@ ///Moth wings! They can flutter in low-grav and burn off in heat /obj/item/organ/external/wings/moth + name = "moth wings" + desc = "Spread your wings and FLOOOOAAAAAT!" + feature_key = "moth_wings" preference = "feature_moth_wings" layers = EXTERNAL_BEHIND | EXTERNAL_FRONT diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 15284c073ce..393713f4571 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -242,7 +242,7 @@ /obj/item/organ/internal/heart/freedom name = "heart of freedom" desc = "This heart pumps with the passion to give... something freedom." - organ_flags = ORGAN_SYNTHETIC //the power of freedom prevents heart attacks + organ_flags = ORGAN_SYNTHETIC //the power of freedom prevents heart attacks /// The cooldown until the next time this heart can give the host an adrenaline boost. COOLDOWN_DECLARE(adrenaline_cooldown) diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm index 1a7ced99076..023788764ce 100644 --- a/code/modules/surgery/organs/helpers.dm +++ b/code/modules/surgery/organs/helpers.dm @@ -30,7 +30,7 @@ return (locate(typepath) in internal_organs + external_organs) -/mob/living/carbon/getorganszone(zone, subzones = 0) +/mob/living/carbon/getorganszone(zone, subzones = 0, external = FALSE) var/list/returnorg = list() if(subzones) // Include subzones - groin for chest, eyes and mouth for head diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index fb0f462d010..71147e3cb43 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -34,11 +34,11 @@ if(istype(tool, /obj/item/borg/apparatus/organ_storage)) if(!tool.contents.len) to_chat(user, span_warning("There is nothing inside [tool]!")) - return -1 + return SURGERY_STEP_FAIL var/obj/item/organ_storage_contents = tool.contents[1] if(!isbodypart(organ_storage_contents)) to_chat(user, span_warning("[organ_storage_contents] cannot be attached!")) - return -1 + return SURGERY_STEP_FAIL tool = organ_storage_contents if(istype(tool, /obj/item/bodypart)) var/obj/item/bodypart/bodypart_to_attach = tool @@ -49,7 +49,7 @@ var/obj/item/bodypart/chest/target_chest = human_target.get_bodypart(BODY_ZONE_CHEST) if(!(bodypart_to_attach.bodytype & target_chest.acceptable_bodytype)) to_chat(user, span_warning("[bodypart_to_attach] doesn't match the patient's morphology.")) - return -1 + return SURGERY_STEP_FAIL if(human_target.dna.species.id != bodypart_to_attach.limb_id) organ_rejection_dam = 30 @@ -59,14 +59,14 @@ span_notice("[user] begins to replace [target]'s [parse_zone(target_zone)].")) else to_chat(user, span_warning("[tool] isn't the right type for [parse_zone(target_zone)].")) - return -1 + return SURGERY_STEP_FAIL else if(target_zone == BODY_ZONE_L_ARM || target_zone == BODY_ZONE_R_ARM) display_results(user, target, span_notice("You begin to attach [tool] onto [target]..."), span_notice("[user] begins to attach [tool] onto [target]'s [parse_zone(target_zone)]."), span_notice("[user] begins to attach something onto [target]'s [parse_zone(target_zone)].")) else to_chat(user, span_warning("[tool] must be installed onto an arm.")) - return -1 + return SURGERY_STEP_FAIL /datum/surgery_step/add_prosthetic/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) . = ..() diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 37097c18ecf..43a3d7640c3 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -75,7 +75,7 @@ var/fail_prob = 0//100 - fail_prob = success_prob var/advance = FALSE - if(preop(user, target, target_zone, tool, surgery) == -1) + if(preop(user, target, target_zone, tool, surgery) == SURGERY_STEP_FAIL) surgery.step_in_progress = FALSE return FALSE diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index f30d5f2b6032cbd703f357bfee2634f7ad753362..d09f7caf28a0829986678d0dd3d4e8c75a228841 100755 GIT binary patch delta 6950 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 a;Soz_r;_^8XaNBrFJ*akxpEovkpBnIJdP{? delta 6066 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