From e2e15d557944b2a5ca062cf7633f7f4cfa9566e8 Mon Sep 17 00:00:00 2001 From: Luc <89928798+lewcc@users.noreply.github.com> Date: Sun, 25 Sep 2022 12:47:09 -0400 Subject: [PATCH] [GBP: NO UPDATE] Fixes xeno surgery (#19119) * Fixes optable * Xeno surgery works again, but at what cost? --- code/__DEFINES/mobs.dm | 2 +- code/game/machinery/OpTable.dm | 12 +- code/game/machinery/computer/Operating.dm | 14 +- code/game/objects/items.dm | 2 +- .../hallucinations/effects/moderate.dm | 2 +- code/modules/surgery/organs/pain.dm | 8 +- code/modules/surgery/organs_internal.dm | 168 ++++++++++++++---- 7 files changed, 161 insertions(+), 47 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 84b25c97d17..bb4e7e4d30c 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -273,7 +273,7 @@ #define isnewplayer(A) (istype((A), /mob/new_player)) #define isorgan(A) (istype((A), /obj/item/organ/external)) -#define hasorgans(A) (ishuman(A)) +#define hasorgans(A) (iscarbon(A)) #define is_admin(user) (check_rights(R_ADMIN, 0, (user)) != 0) diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 16c001bce66..ff7c8c65297 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -8,7 +8,7 @@ use_power = IDLE_POWER_USE idle_power_usage = 1 active_power_usage = 5 - var/mob/living/carbon/human/patient + var/mob/living/carbon/patient var/obj/machinery/computer/operating/computer buckle_lying = -1 var/no_icon_updates = FALSE //set this to TRUE if you don't want the icons ever changing @@ -64,13 +64,13 @@ * Updates the `patient` var to be the mob occupying the table */ /obj/machinery/optable/proc/update_patient() - var/mob/living/carbon/human/M = locate(/mob/living/carbon/human, loc) - if(M && IS_HORIZONTAL(M)) - patient = M + var/mob/living/carbon/C = locate(/mob/living/carbon, loc) + if(C && IS_HORIZONTAL(C)) + patient = C else patient = null if(!no_icon_updates) - if(patient && patient.pulse) + if(C && C.pulse) icon_state = "table2-active" else icon_state = "table2-idle" @@ -107,7 +107,7 @@ set name = "Climb On Table" set category = "Object" set src in oview(1) - if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table()) + if(usr.stat || !iscarbon(usr) || usr.restrained() || !check_table()) return take_patient(usr, usr) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index fa87540701d..1fae66002c4 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -64,7 +64,7 @@ /obj/machinery/computer/operating/ui_data(mob/user) var/list/data = list() - var/mob/living/carbon/human/occupant + var/mob/living/carbon/occupant if(table) occupant = table.patient data["hasOccupant"] = occupant ? 1 : 0 @@ -111,11 +111,12 @@ occupantData["btFaren"] = ((occupant.bodytemperature - T0C) * (9.0/5.0))+ 32 if(ishuman(occupant) && !(NO_BLOOD in occupant.dna.species.species_traits)) + var/mob/living/carbon/human/H = occupant occupantData["pulse"] = occupant.get_pulse(GETPULSE_TOOL) occupantData["hasBlood"] = 1 occupantData["bloodLevel"] = round(occupant.blood_volume) - occupantData["bloodMax"] = occupant.max_blood - occupantData["bloodPercent"] = round(100*(occupant.blood_volume/occupant.max_blood), 0.01) //copy pasta ends here + occupantData["bloodMax"] = H.max_blood + occupantData["bloodPercent"] = round(100*(occupant.blood_volume/H.max_blood), 0.01) //copy pasta ends here occupantData["bloodType"] = occupant.dna.blood_type if(length(occupant.surgeries)) @@ -198,7 +199,12 @@ if(isNewPatient) atom_say("New patient detected, loading stats") - atom_say("[table.patient], [table.patient.dna.blood_type] blood, [patientStatus]") + var/blood_type_msg + if(ishuman(table.patient)) + blood_type_msg = table.patient.dna.blood_type + else + blood_type_msg = "\[ERROR: UNKNOWN\]" + atom_say("[table.patient], [blood_type_msg] blood, [patientStatus]") SStgui.update_uis(src) patientStatusHolder = table.patient.stat currentPatient = table.patient diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6891cf3b2f1..80b5a32c17c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -263,7 +263,7 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons /obj/item/attack_hand(mob/user as mob, pickupfireoverride = FALSE) if(!user) return 0 - if(hasorgans(user)) + if(ishuman(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/external/temp = H.bodyparts_by_name["r_hand"] if(user.hand) diff --git a/code/modules/hallucinations/effects/moderate.dm b/code/modules/hallucinations/effects/moderate.dm index b48517304ee..b4569d1189f 100644 --- a/code/modules/hallucinations/effects/moderate.dm +++ b/code/modules/hallucinations/effects/moderate.dm @@ -91,7 +91,7 @@ /obj/effect/hallucination/fake_item/attack_hand(mob/living/user) if(user != target) return - if(hasorgans(user)) + if(ishuman(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/external/temp = H.bodyparts_by_name["r_hand"] if(user.hand) diff --git a/code/modules/surgery/organs/pain.dm b/code/modules/surgery/organs/pain.dm index f78cfb2f8f9..007afbed201 100644 --- a/code/modules/surgery/organs/pain.dm +++ b/code/modules/surgery/organs/pain.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/human +/mob/living/carbon var/last_pain_message = "" var/next_pain_time = 0 @@ -7,7 +7,7 @@ * * Returns TRUE if the mob can feel pain, FALSE otherwise */ -/mob/living/carbon/human/proc/can_feel_pain() +/mob/living/carbon/proc/can_feel_pain() if(stat >= UNCONSCIOUS) return FALSE if(reagents.has_reagent("morphine")) @@ -21,7 +21,7 @@ // partname is the name of a body part // amount is a num from 1 to 100 -/mob/living/carbon/human/proc/pain(partname, amount) +/mob/living/carbon/proc/pain(partname, amount) if(!can_feel_pain()) return if(world.time < next_pain_time) @@ -41,7 +41,7 @@ // message is the custom message to be displayed -/mob/living/carbon/human/proc/custom_pain(message) +/mob/living/carbon/proc/custom_pain(message) if(!can_feel_pain()) return diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index f7de06c23e8..b92cc9c6a5a 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -50,9 +50,18 @@ /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) + requires_bodypart = FALSE // xenos just don't have "bodyparts" + 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) target_mobtypes = list(/mob/living/carbon/alien/humanoid) - steps = list(/datum/surgery_step/saw_carapace,/datum/surgery_step/cut_carapace, /datum/surgery_step/retract_carapace,/datum/surgery_step/proxy/manipulate_organs,) + steps = list( + /datum/surgery_step/saw_carapace, + /datum/surgery_step/cut_carapace, + /datum/surgery_step/retract_carapace, + /datum/surgery_step/proxy/manipulate_organs/alien, + /datum/surgery_step/generic/seal_carapace + ) + + /datum/surgery/organ_manipulation/can_start(mob/user, mob/living/carbon/target) @@ -122,11 +131,49 @@ /datum/surgery/intermediate/bleeding ) +// have to redefine all of these because xenos don't technically have bodyparts. +/datum/surgery/intermediate/manipulate/extract/xeno + requires_bodypart = FALSE + +/datum/surgery/intermediate/manipulate/implant/xeno + requires_bodypart = FALSE + +/datum/surgery/intermediate/manipulate/mend/xeno + requires_bodypart = FALSE + +/datum/surgery/intermediate/manipulate/clean/xeno + requires_bodypart = FALSE + +/datum/surgery_step/proxy/manipulate_organs/alien + name = "Manipulate Organs Xeno (proxy)" + branches = list( + /datum/surgery/intermediate/manipulate/extract/xeno, + /datum/surgery/intermediate/manipulate/implant/xeno, + /datum/surgery/intermediate/manipulate/mend/xeno, + /datum/surgery/intermediate/manipulate/clean/xeno + ) + // Internal surgeries. /datum/surgery_step/internal can_infect = TRUE blood_level = SURGERY_BLOODSPREAD_HANDS +/** + * Get an internal list of organs for a zone (or an external organ). + * + * Helper function since we end up calling this a ton to work with carbons + */ +/datum/surgery_step/internal/proc/get_organ_list(target_zone, mob/living/carbon/target, obj/item/organ/external/affected) + var/list/organs + + if(affected && istype(affected)) + organs = affected.internal_organs + else + organs = target.get_organs_zone(target_zone) + + return organs + + /datum/surgery_step/internal/manipulate_organs/mend name = "mend organs" allowed_tools = list( @@ -146,7 +193,7 @@ return tool_name -/datum/surgery_step/internal/manipulate_organs/mend/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) +/datum/surgery_step/internal/manipulate_organs/mend/begin_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) var/tool_name = get_tool_name(tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) @@ -157,8 +204,9 @@ var/any_organs_damaged = FALSE + var/list/organs = get_organ_list(target_zone, target, affected) - for(var/obj/item/organ/internal/I in affected.internal_organs) + for(var/obj/item/organ/internal/I in organs) if(I && I.damage) any_organs_damaged = TRUE if(!I.is_robotic() && !istype(tool, /obj/item/stack/nanopaste)) @@ -177,8 +225,8 @@ return SURGERY_BEGINSTEP_SKIP if(affected) - var/mob/living/carbon/human/H = target - H.custom_pain("The pain in your [affected.name] is living hell!") + var/mob/living/carbon/C = target + C.custom_pain("The pain in your [affected.name] is living hell!") return ..() @@ -188,7 +236,9 @@ if(!hasorgans(target)) return SURGERY_STEP_INCOMPLETE - for(var/obj/item/organ/internal/I in affected.internal_organs) + var/list/organs = get_organ_list(target_zone, target, affected) + + for(var/obj/item/organ/internal/I in organs) if(I) I.surgeryize() if(I && I.damage) @@ -209,11 +259,12 @@ /datum/surgery_step/internal/manipulate_organs/mend/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) if(!hasorgans(target)) return SURGERY_STEP_INCOMPLETE + var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message( - " [user]'s hand slips, getting mess and tearing the inside of [target]'s [affected.name] with [tool]!", - " Your hand slips, getting mess and tearing the inside of [target]'s [affected.name] with [tool]!" + " [user]'s hand slips, getting messy and tearing the inside of [target]'s [parse_zone(target_zone)] with [tool]!", + " Your hand slips, getting messy and tearing the inside of [target]'s [parse_zone(target_zone)] with [tool]!" ) var/dam_amt = 2 @@ -224,9 +275,12 @@ else if(istype(tool, /obj/item/stack/medical/bruise_pack) || istype(tool, /obj/item/stack/nanopaste)) dam_amt = 5 target.adjustToxLoss(10) - affected.receive_damage(5) + if(affected) + affected.receive_damage(5) - for(var/obj/item/organ/internal/I in affected.internal_organs) + var/list/organs = get_organ_list(target_zone, target, affected) + + for(var/obj/item/organ/internal/I in organs) if(I && I.damage && !(I.tough)) I.receive_damage(dam_amt,0) @@ -421,26 +475,27 @@ var/obj/item/reagent_containers/C = tool - var/mob/living/carbon/human/H = target - var/obj/item/organ/external/affected = H.get_organ(user.zone_selected) + var/obj/item/organ/external/affected = target.get_organ(user.zone_selected) - for(var/obj/item/organ/internal/I in affected.internal_organs) - if(I) - if(C.reagents.total_volume <= 0) //end_step handles if there is not enough reagent - user.visible_message( - "[user] notices [tool] is empty.", - "You notice [tool] is empty." - ) - return SURGERY_BEGINSTEP_SKIP + var/list/organs = get_organ_list(target_zone, target, affected) - var/msg = "[user] starts pouring some of [tool] over [target]'s [I.name]." - var/self_msg = "You start pouring some of [tool] over [target]'s [I.name]." - if(istype(C, /obj/item/reagent_containers/syringe)) - msg = "[user] begins injecting [tool] into [target]'s [I.name]." - self_msg = "You begin injecting [tool] into [target]'s [I.name]." - user.visible_message(msg, self_msg) - if(H && affected) - H.custom_pain("Something burns horribly in your [affected.name]!") + for(var/obj/item/organ/internal/I in organs) + if(!I) + continue + if(C.reagents.total_volume <= 0) //end_step handles if there is not enough reagent + user.visible_message( + "[user] notices [tool] is empty.", + "You notice [tool] is empty." + ) + return SURGERY_BEGINSTEP_SKIP + + var/msg = "[user] starts pouring some of [tool] over [target]'s [I.name]." + var/self_msg = "You start pouring some of [tool] over [target]'s [I.name]." + if(istype(C, /obj/item/reagent_containers/syringe)) + msg = "[user] begins injecting [tool] into [target]'s [I.name]." + self_msg = "You begin injecting [tool] into [target]'s [I.name]." + user.visible_message(msg, self_msg) + target.custom_pain("Something burns horribly in your [parse_zone(target_zone)]!") return ..() @@ -452,6 +507,8 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) + var/list/organs = get_organ_list(target_zone, target, affected) + var/obj/item/reagent_containers/C = tool var/datum/reagents/R = C.reagents var/ethanol = 0 //how much alcohol is in the thing @@ -467,7 +524,7 @@ spaceacillin = R.get_reagent_amount("spaceacillin") - for(var/obj/item/organ/internal/I in affected.internal_organs) + for(var/obj/item/organ/internal/I in organs) if(!I) // if you have a null organ I wish you the best continue if(I.germ_level < INFECTION_LEVEL_ONE / 2 && !(I.status & ORGAN_DEAD)) // not dead, don't need to inject mito either @@ -735,4 +792,55 @@ user.visible_message(msg, self_msg) return SURGERY_STEP_RETRY +// redefine cauterize for every step because of course it relies on get_organ() +/datum/surgery_step/generic/seal_carapace/ + name = "seal carapace" + + allowed_tools = list( + /obj/item/scalpel/laser = 100, + TOOL_CAUTERY = 100, + /obj/item/clothing/mask/cigarette = 90, + /obj/item/lighter = 60, + TOOL_WELDER = 30 + ) + + time = 2.4 SECONDS + +/datum/surgery_step/generic/seal_carapace/proc/zone_name(target_zone) + var/zone = target_zone + + if(target_zone == BODY_ZONE_CHEST) + zone = "torso" + else if(target_zone == BODY_ZONE_PRECISE_GROIN) + zone = "lower abdomen" + + return zone + +/datum/surgery_step/generic/seal_carapace/begin_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/zone = zone_name(target_zone) + user.visible_message( + "[user] is beginning to cauterize the incision on [target]'s [zone] with \the [tool].", + "You are beginning to cauterize the incision on [target]'s [zone] with \the [tool]." + ) + target.custom_pain("Your [zone] is being burned!") + return ..() + +/datum/surgery_step/generic/seal_carapace/end_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/zone = zone_name(target_zone) + user.visible_message( + "[user] cauterizes the incision on [target]'s [zone] with \the [tool].", + "You cauterize the incision on [target]'s [zone] with \the [tool]." + ) + return SURGERY_STEP_CONTINUE + +/datum/surgery_step/generic/seal_carapace/fail_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/zone = zone_name(target_zone) + user.visible_message( + "[user]'s hand slips, leaving a small burn on [target]'s [zone] with \the [tool]!", + "Your hand slips, leaving a small burn on [target]'s [zone] with \the [tool]!" + ) + target.apply_damage(3, BURN, target_zone) + return SURGERY_STEP_RETRY + + #undef MITO_REVIVAL_COST