From 9fcde12b4ff6ce5155919907ad85c3fcf3e6714d Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Sun, 28 Sep 2014 01:21:36 +0930 Subject: [PATCH] Organ rewrite mapclean attempt. --- baystation12.dme | 9 +- code/ZAS/Phoron.dm | 16 +- code/controllers/hooks-defs.dm | 2 +- code/datums/diseases/appendicitis.dm | 3 +- code/datums/spells/inflict_handler.dm | 4 +- code/game/gamemodes/cult/runes.dm | 4 +- .../mutiny/directives/ipc_virus_directive.dm | 4 +- code/game/gamemodes/newobjective.dm | 2 +- code/game/machinery/bioprinter.dm | 71 +++ code/game/machinery/bots/mulebot.dm | 5 +- code/game/machinery/cloning.dm | 4 +- code/game/machinery/computer/cloning.dm | 2 +- code/game/machinery/flasher.dm | 2 +- code/game/objects/items.dm | 32 +- code/game/objects/items/devices/scanners.dm | 2 +- .../items/weapons/grenades/flashbang.dm | 4 +- .../objects/items/weapons/surgery_tools.dm | 2 +- code/game/objects/items/weapons/tools.dm | 2 + code/game/turfs/simulated.dm | 38 +- code/modules/food/recipes_microwave.dm | 4 +- code/modules/mob/living/carbon/alien/alien.dm | 3 + .../carbon/alien/humanoid/caste/drone.dm | 2 +- .../mob/living/carbon/alien/humanoid/life.dm | 2 +- .../mob/living/carbon/alien/larva/life.dm | 2 +- code/modules/mob/living/carbon/brain/MMI.dm | 5 +- .../mob/living/carbon/brain/brain_item.dm | 102 ++-- code/modules/mob/living/carbon/brain/death.dm | 2 +- .../mob/living/carbon/brain/posibrain.dm | 2 - .../mob/living/carbon/carbon_defines.dm | 1 - .../mob/living/carbon/human/examine.dm | 9 +- code/modules/mob/living/carbon/human/human.dm | 25 +- .../mob/living/carbon/human/human_damage.dm | 28 +- code/modules/mob/living/carbon/human/life.dm | 27 +- .../mob/living/carbon/metroid/metroid.dm | 5 + code/modules/mob/living/carbon/monkey/life.dm | 2 +- code/modules/mob/living/carbon/species.dm | 18 +- code/modules/mob/living/living.dm | 6 + code/modules/organs/blood.dm | 120 +++-- code/modules/organs/organ.dm | 16 + code/modules/organs/organ_external.dm | 11 +- code/modules/organs/organ_internal.dm | 84 ++- code/modules/organs/organ_objects.dm | 232 +++++++++ code/modules/reagents/Chemistry-Reagents.dm | 59 +-- .../reagent_containers/food/snacks.dm | 18 +- .../reagents/reagent_containers/syringes.dm | 2 +- code/modules/surgery/appendix.dm | 89 ---- code/modules/surgery/bones.dm | 8 +- code/modules/surgery/braincore.dm | 279 ---------- code/modules/surgery/brainrepair.dm | 68 +++ code/modules/surgery/encased.dm | 220 ++++++++ code/modules/surgery/eye.dm | 5 +- code/modules/surgery/generic.dm | 8 +- code/modules/surgery/implant.dm | 6 +- code/modules/surgery/organs_internal.dm | 493 ++++++++++++++++++ code/modules/surgery/other.dm | 34 +- code/modules/surgery/ribcage.dm | 335 ------------ code/modules/surgery/slimes.dm | 93 ++++ code/modules/surgery/surgery.dm | 7 +- code/modules/virus2/effect.dm | 2 +- icons/obj/surgery.dmi | Bin 10466 -> 14638 bytes maps/tgstation2.dmm | 4 +- 61 files changed, 1611 insertions(+), 1035 deletions(-) create mode 100644 code/game/machinery/bioprinter.dm create mode 100644 code/modules/organs/organ_objects.dm delete mode 100644 code/modules/surgery/appendix.dm delete mode 100644 code/modules/surgery/braincore.dm create mode 100644 code/modules/surgery/brainrepair.dm create mode 100644 code/modules/surgery/encased.dm create mode 100644 code/modules/surgery/organs_internal.dm delete mode 100644 code/modules/surgery/ribcage.dm create mode 100644 code/modules/surgery/slimes.dm diff --git a/baystation12.dme b/baystation12.dme index d09a530659b..1c200c9afc0 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -292,6 +292,7 @@ #include "code\game\machinery\Beacon.dm" #include "code\game\machinery\bees_apiary.dm" #include "code\game\machinery\bees_items.dm" +#include "code\game\machinery\bioprinter.dm" #include "code\game\machinery\buttons.dm" #include "code\game\machinery\cell_charger.dm" #include "code\game\machinery\cloning.dm" @@ -1110,6 +1111,7 @@ #include "code\modules\organs\organ.dm" #include "code\modules\organs\organ_external.dm" #include "code\modules\organs\organ_internal.dm" +#include "code\modules\organs\organ_objects.dm" #include "code\modules\organs\pain.dm" #include "code\modules\organs\wound.dm" #include "code\modules\paperwork\carbonpaper.dm" @@ -1345,17 +1347,18 @@ #include "code\modules\shuttles\shuttle_supply.dm" #include "code\modules\shuttles\shuttles_multi.dm" #include "code\modules\supermatter\supermatter.dm" -#include "code\modules\surgery\appendix.dm" #include "code\modules\surgery\bones.dm" -#include "code\modules\surgery\braincore.dm" +#include "code\modules\surgery\brainrepair.dm" +#include "code\modules\surgery\encased.dm" #include "code\modules\surgery\eye.dm" #include "code\modules\surgery\face.dm" #include "code\modules\surgery\generic.dm" #include "code\modules\surgery\headreattach.dm" #include "code\modules\surgery\implant.dm" +#include "code\modules\surgery\organs_internal.dm" #include "code\modules\surgery\other.dm" -#include "code\modules\surgery\ribcage.dm" #include "code\modules\surgery\robolimbs.dm" +#include "code\modules\surgery\slimes.dm" #include "code\modules\surgery\surgery.dm" #include "code\modules\vehicles\cargo_train.dm" #include "code\modules\vehicles\train.dm" diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index 98ab1278257..6cd983732ba 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -117,13 +117,17 @@ obj/var/contaminated = 0 /mob/living/carbon/human/proc/burn_eyes() //The proc that handles eye burning. - if(prob(20)) src << "\red Your eyes burn!" + if(!species.has_organ["eyes"]) + return + var/datum/organ/internal/eyes/E = internal_organs_by_name["eyes"] - E.damage += 2.5 - eye_blurry = min(eye_blurry+1.5,50) - if (prob(max(0,E.damage - 15) + 1) &&!eye_blind) - src << "\red You are blinded!" - eye_blind += 20 + if(E) + if(prob(20)) src << "\red Your eyes burn!" + E.damage += 2.5 + eye_blurry = min(eye_blurry+1.5,50) + if (prob(max(0,E.damage - 15) + 1) &&!eye_blind) + src << "\red You are blinded!" + eye_blind += 20 /mob/living/carbon/human/proc/pl_head_protected() //Checks if the head is adequately sealed. diff --git a/code/controllers/hooks-defs.dm b/code/controllers/hooks-defs.dm index 1cd7c4aad8a..d36fc7a7c7f 100644 --- a/code/controllers/hooks-defs.dm +++ b/code/controllers/hooks-defs.dm @@ -33,7 +33,7 @@ /** * Debrained hook. * Called in brain_item.dm when someone gets debrained. - * Parameters: var/obj/item/brain + * Parameters: var/obj/item/organ/brain */ /hook/debrain diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index dba42d74d64..a9959ef0636 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -19,7 +19,8 @@ if(istype(affected_mob,/mob/living/carbon/human)) var/mob/living/carbon/human/H = affected_mob - if(H.species.name == "Diona" || H.species.name == "Machine" || H.species.name == "Vox") src.cure() + if(!H.internal_organs_by_name["appendix"]) + src.cure() if(stage == 1) if(affected_mob.op_stage.appendix == 2.0) diff --git a/code/datums/spells/inflict_handler.dm b/code/datums/spells/inflict_handler.dm index ac85b18ae3b..496eac91956 100644 --- a/code/datums/spells/inflict_handler.dm +++ b/code/datums/spells/inflict_handler.dm @@ -26,8 +26,8 @@ if("gib_brain") if(ishuman(target) || ismonkey(target)) var/mob/living/carbon/C = target - if(C.brain_op_stage != 4) // Their brain is already taken out - var/obj/item/brain/B = new(C.loc) + if(!C.has_brain()) // Their brain is already taken out + var/obj/item/organ/brain/B = new(C.loc) B.transfer_identity(C) target.gib() if("disintegrate") diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 6750f7c83eb..590df9cd07d 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -568,8 +568,8 @@ var/list/sacrificed = list() if(!(iscultist(V))) victims += V//Checks for cult status and mob type for(var/obj/item/I in src.loc)//Checks for MMIs/brains/Intellicards - if(istype(I,/obj/item/brain)) - var/obj/item/brain/B = I + if(istype(I,/obj/item/organ/brain)) + var/obj/item/organ/brain/B = I victims += B.brainmob else if(istype(I,/obj/item/device/mmi)) var/obj/item/device/mmi/B = I diff --git a/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm b/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm index 63c3f7d3c86..e035b665c9f 100644 --- a/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm +++ b/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm @@ -62,11 +62,11 @@ datum/directive/ipc_virus/get_remaining_orders() return text -/hook/debrain/proc/debrain_directive(obj/item/brain/B) +/hook/debrain/proc/debrain_directive(var/obj/item/organ/brain/B) var/datum/directive/ipc_virus/D = get_directive("ipc_virus") if (!D) return 1 - if(D.brains_to_enslave.Find(B.brainmob.mind)) + if(B && B.brainmob && B.brainmob.mind && D.brains_to_enslave.Find(B.brainmob.mind)) D.brains_to_enslave.Remove(B.brainmob.mind) return 1 diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index 70901add189..c2608cfa3d4 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -1376,7 +1376,7 @@ datum var/list/all_items = owner.current.get_contents() for(var/obj/item/device/mmi/mmi in all_items) if(mmi.brainmob&&mmi.brainmob.mind==target) return 1 - for(var/obj/item/brain/brain in all_items) + for(var/obj/item/organ/brain/brain in all_items) if(brain.brainmob&&brain.brainmob.mind==target) return 1 return 0 diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm new file mode 100644 index 00000000000..4ce50d404c5 --- /dev/null +++ b/code/game/machinery/bioprinter.dm @@ -0,0 +1,71 @@ +//These machines are mostly just here for debugging/spawning. Skeletons of the feature to come. + +/obj/machinery/bioprinter + name = "bioprinter" + desc = "It's a machine that grows replacement organs." + icon = 'icons/obj/surgery.dmi' + + icon_state = "bioprinter" + + var/prints_prosthetics + var/stored_matter = 200 + var/loaded_dna //Blood sample for DNA hashing. + var/list/products = list( + "heart" = list(/obj/item/organ/heart, 50), + "lungs" = list(/obj/item/organ/lungs, 40), + "kidneys" = list(/obj/item/organ/kidneys,20), + "eyes" = list(/obj/item/organ/eyes, 30), + "liver" = list(/obj/item/organ/liver, 50) + ) + +/obj/machinery/bioprinter/prosthetics + name = "prosthetics fabricator" + desc = "It's a machine that prints prosthetic organs." + prints_prosthetics = 1 + +/obj/machinery/bioprinter/attack_hand(mob/user) + + var/choice = input("What would you like to print?") as null|anything in products + if(!choice) + return + + if(stored_matter >= products[choice][2]) + + stored_matter -= products[choice][2] + var/new_organ = products[choice][1] + var/obj/item/organ/O = new new_organ(get_turf(src)) + + if(prints_prosthetics) + O.robotic = 2 + else if(loaded_dna) + visible_message("The printer would be using the DNA sample if it was coded.") + //TODO: Copy DNA hash or donor reference over to new organ. + + visible_message("The bioprinter spits out a new organ.") + + else + user << "There is not enough matter in the printer." + +/obj/machinery/bioprinter/attackby(obj/item/weapon/W, mob/user) + + // DNA sample from syringe. + if(!prints_prosthetics && istype(W,/obj/item/weapon/reagent_containers/syringe)) + user << "You inject the blood sample into the bioprinter, but it isn't coded yet." + return + // Meat for biomass. + else if(!prints_prosthetics && istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) + user << "\blue \The [src] processes \the [W]." + stored_matter += 50 + user.drop_item() + del(W) + return + // Steel for matter. + else if(prints_prosthetics && istype(W, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = W + user << "\blue \The [src] processes \the [W]." + stored_matter += M.amount * 10 + user.drop_item() + del(W) + return + else + return..() \ No newline at end of file diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 1762225088a..ce76680b0d9 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -803,10 +803,7 @@ H.apply_damage(0.5*damage, BRUTE, "l_arm") H.apply_damage(0.5*damage, BRUTE, "r_arm") - var/obj/effect/decal/cleanable/blood/B = new(src.loc) - B.blood_DNA = list() - B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - + blood_splatter(src,H,1) bloodiness += 4 // player on mulebot attempted to move diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 5e1fbbe50da..04f5efa5185 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -72,12 +72,12 @@ return var/mob/selected = null - for(var/mob/M in player_list) + for(var/mob/living/M in player_list) //Dead people only thanks! if ((M.stat != 2) || (!M.client)) continue //They need a brain! - if ((istype(M, /mob/living/carbon/human)) && (M:brain_op_stage >= 4.0)) + if ((istype(M, /mob/living/carbon/human)) && (!M.has_brain())) continue if (M.ckey == find_key) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 9ce8ccb4fc6..47eb7ca5583 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -337,7 +337,7 @@ if ((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna)) scantemp = "Error: Unable to locate valid genetic data." return - if (subject.brain_op_stage == 4.0) + if (!subject.has_brain()) scantemp = "Error: No signs of intelligence detected." return if (subject.suiciding == 1) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index cf05308e400..345d9f44d5d 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -81,7 +81,7 @@ if (istype(O, /mob/living/carbon/human)) var/mob/living/carbon/human/H = O var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if ((E.damage > E.min_bruised_damage && prob(E.damage + 50))) + if (E && (E.damage > E.min_bruised_damage && prob(E.damage + 50))) flick("e_flash", O:flash) E.damage += rand(1, 5) else diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6e1cc86633c..b4155d6fcae 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -53,7 +53,7 @@ Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. */ var/list/sprite_sheets_obj = null - + /obj/item/device icon = 'icons/obj/device.dmi' @@ -516,8 +516,8 @@ user << "\red You're going to need to remove the eye covering first." return - if(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//Aliens don't have eyes./N slimes also don't have eyes! - user << "\red You cannot locate any eyes on this creature!" + if(!M.has_eyes()) + user << "\red You cannot locate any eyes on [M]!" return user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" @@ -533,20 +533,22 @@ M.weakened += 4 M.adjustBruteLoss(10) */ - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] has been stabbed in the eye with [src] by [user].", 1) - M << "\red [user] stabs you in the eye with [src]!" - user << "\red You stab [M] in the eye with [src]!" - else - user.visible_message( \ - "\red [user] has stabbed themself with [src]!", \ - "\red You stab yourself in the eyes with [src]!" \ - ) + if(istype(M, /mob/living/carbon/human)) + var/datum/organ/internal/eyes/eyes = H.internal_organs_by_name["eyes"] - if(!eyes) - return + + if(M != user) + for(var/mob/O in (viewers(M) - user - M)) + O.show_message("\red [M] has been stabbed in the eye with [src] by [user].", 1) + M << "\red [user] stabs you in the eye with [src]!" + user << "\red You stab [M] in the eye with [src]!" + else + user.visible_message( \ + "\red [user] has stabbed themself with [src]!", \ + "\red You stab yourself in the eyes with [src]!" \ + ) + eyes.damage += rand(3,4) if(eyes.damage >= eyes.min_bruised_damage) if(M.stat != 2) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index d3149ab90f8..aa7e260371b 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -173,7 +173,7 @@ REAGENT SCANNER // user.show_message("\blue Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.") if (M.has_brain_worms()) user.show_message("\red Subject suffering from aberrant brain activity. Recommend further scanning.") - else if (M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0) + else if (M.getBrainLoss() >= 100 || !M.has_brain()) user.show_message("\red Subject is brain dead.") else if (M.getBrainLoss() >= 60) user.show_message("\red Severe brain damage detected. Subject likely to have mental retardation.") diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index dd60f16645a..f5ad4fa9fde 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -20,7 +20,7 @@ var/damage = round(30/(get_dist(B,get_turf(src))+1)) B.health -= damage B.update_icon() - + new/obj/effect/effect/smoke/flashbang(src.loc) del(src) return @@ -84,7 +84,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if (E.damage >= E.min_bruised_damage) + if (E && E.damage >= E.min_bruised_damage) M << "\red Your eyes start to burn badly!" if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang))) if (E.damage >= E.min_broken_damage) diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm index ddadcfddd8c..3080c05f09e 100644 --- a/code/game/objects/items/weapons/surgery_tools.dm +++ b/code/game/objects/items/weapons/surgery_tools.dm @@ -773,7 +773,7 @@ LOOK FOR SURGERY.DM*/ log_attack("[user.name] ([user.ckey]) debrained [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - var/obj/item/brain/B = new(M.loc) + var/obj/item/organ/brain/B = new(M.loc) B.transfer_identity(M) M:brain_op_stage = 4.0 diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index f4400132e80..fdb6a93b2e4 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -357,6 +357,8 @@ if(istype(user, /mob/living/carbon/human)) var/mob/living/carbon/human/H = user var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] + if(!E) + return if(H.species.flags & IS_SYNTHETIC) return switch(safety) diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 19223c48f1c..42a63f26e58 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -153,50 +153,16 @@ B.virus2 = virus_copylist(M.virus2) return 1 //we bloodied the floor - - - //if there isn't a blood decal already, make one. - var/obj/effect/decal/cleanable/blood/newblood = new /obj/effect/decal/cleanable/blood(src) - - //Species-specific blood. - if(M.species) - newblood.basecolor = M.species.blood_color - else - newblood.basecolor = "#A10808" - - newblood.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - newblood.virus2 = virus_copylist(M.virus2) - newblood.update_icon() - + blood_splatter(src,M.get_blood(M.vessel),1) return 1 //we bloodied the floor // Only adds blood on the floor -- Skie /turf/simulated/proc/add_blood_floor(mob/living/carbon/M as mob) if(istype(M, /mob/living/carbon/monkey)) - - var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) - this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - this.basecolor = "#A10808" - this.update_icon() - - else if(istype(M,/mob/living/carbon/human)) - - var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) - var/mob/living/carbon/human/H = M - - //Species-specific blood. - if(H.species) - this.basecolor = H.species.blood_color - else - this.basecolor = "#A10808" - this.update_icon() - - this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - + blood_splatter(src,M,1) else if( istype(M, /mob/living/carbon/alien )) var/obj/effect/decal/cleanable/blood/xeno/this = new /obj/effect/decal/cleanable/blood/xeno(src) this.blood_DNA["UNKNOWN BLOOD"] = "X*" - else if( istype(M, /mob/living/silicon/robot )) new /obj/effect/decal/cleanable/blood/oil(src) diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index 95183949160..fdd28f5bccb 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -135,7 +135,7 @@ I said no! /datum/recipe/brainburger items = list( /obj/item/weapon/reagent_containers/food/snacks/bun, - /obj/item/brain + /obj/item/organ/brain ) result = /obj/item/weapon/reagent_containers/food/snacks/brainburger @@ -1063,7 +1063,7 @@ I said no! /obj/item/weapon/reagent_containers/food/snacks/egg, /obj/item/weapon/reagent_containers/food/snacks/egg, /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/brain + /obj/item/organ/brain ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 23d5416fcae..214c091c3e8 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -202,6 +202,9 @@ Des: Removes all infected images from the alien. del(I) return +/mob/living/carbon/alien/has_eyes() + return 0 + #undef HEAT_DAMAGE_LEVEL_1 #undef HEAT_DAMAGE_LEVEL_2 #undef HEAT_DAMAGE_LEVEL_3 diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm index 2b084ce8b5c..6b7752f8137 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -27,7 +27,7 @@ // Queen check var/no_queen = 1 for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) - if(!Q.key && Q.brain_op_stage != 4) + if(!Q.key && Q.has_brain()) continue no_queen = 0 diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index defcc968d13..f1910fcfe30 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -304,7 +304,7 @@ blinded = 1 silent = 0 else //ALIVE. LIGHTS ARE ON - if(health < config.health_threshold_dead || brain_op_stage == 4.0) + if(health < config.health_threshold_dead || !has_brain()) death() blinded = 1 stat = DEAD diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 9bb6ae43767..97abbdec382 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -222,7 +222,7 @@ FUCK YOU MORE FAT CODE -Hawk*/ blinded = 1 silent = 0 else //ALIVE. LIGHTS ARE ON - if(health < -25 || brain_op_stage == 4.0) + if(health < -25 || !has_brain()) death() blinded = 1 silent = 0 diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 6959828f9b5..ae2ed011925 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -22,7 +22,7 @@ var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm. attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O,/obj/item/brain) && !brainmob) //Time to stick a brain in it --NEO + if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO if(!O:brainmob) user << "\red You aren't sure where this brain came from, but you're pretty sure it's a useless brain." return @@ -61,6 +61,7 @@ return ..() + //TODO: ORGAN REMOVAL UPDATE. Make the brain remain in the MMI so it doesn't lose organ data. attack_self(mob/user as mob) if(!brainmob) user << "\red You upend the MMI, but there's nothing in it." @@ -68,7 +69,7 @@ user << "\red You upend the MMI, but the brain is clamped into place." else user << "\blue You upend the MMI, spilling the brain onto the floor." - var/obj/item/brain/brain = new(user.loc) + var/obj/item/organ/brain/brain = new(user.loc) brainmob.container = null//Reset brainmob mmi var. brainmob.loc = brain//Throw mob into brain. living_mob_list -= brainmob//Get outta here diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 27b9da88e88..d2ba4fbb949 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -1,7 +1,7 @@ -/obj/item/brain +/obj/item/organ/brain name = "brain" - desc = "A piece of juicy meat found in a persons head." - icon = 'icons/obj/surgery.dmi' + health = 400 //They need to live awhile longer than other organs. + desc = "A piece of juicy meat found in a person's head." icon_state = "brain2" flags = TABLEPASS force = 1.0 @@ -11,32 +11,32 @@ throw_range = 5 origin_tech = "biotech=3" attack_verb = list("attacked", "slapped", "whacked") + prosthetic_name = "cyberbrain" + prosthetic_icon = "brain-prosthetic" + organ_tag = "brain" var/mob/living/carbon/brain/brainmob = null - New() - ..() - //Shifting the brain "mob" over to the brain object so it's easier to keep track of. --NEO - //WASSSSSUUUPPPP /N - spawn(5) - if(brainmob && brainmob.client) - brainmob.client.screen.len = null //clear the hud +/obj/item/organ/brain/New() + ..() + spawn(5) + if(brainmob && brainmob.client) + brainmob.client.screen.len = null //clear the hud - proc - transfer_identity(var/mob/living/carbon/H) - name = "[H]'s brain" - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.dna = H.dna.Clone() - brainmob.timeofhostdeath = H.timeofdeath - if(H.mind) - H.mind.transfer_to(brainmob) +/obj/item/organ/brain/proc/transfer_identity(var/mob/living/carbon/H) + name = "[H]'s brain" + brainmob = new(src) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.dna = H.dna.Clone() + brainmob.timeofhostdeath = H.timeofdeath + if(H.mind) + H.mind.transfer_to(brainmob) - brainmob << "\blue You feel slightly disoriented. That's normal when you're just a brain." - callHook("debrain", list(brainmob)) + brainmob << "\blue You feel slightly disoriented. That's normal when you're just a brain." + callHook("debrain", list(brainmob)) -/obj/item/brain/examine() // -- TLE +/obj/item/organ/brain/examine() // -- TLE set src in oview(12) if (!( usr )) return @@ -47,53 +47,27 @@ else usr << "This one seems particularly lifeless. Perhaps it will regain some of its luster later.." -/obj/item/brain/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M, /mob)) - return +/obj/item/organ/brain/removed(var/mob/living/target,var/mob/living/user) - add_fingerprint(user) + ..() - if(!(user.zone_sel.selecting == ("head")) || !istype(M, /mob/living/carbon/human)) - return ..() + var/mob/living/simple_animal/borer/borer = target.has_brain_worms() - if( !(locate(/obj/machinery/optable, M.loc) && M.resting) && ( !(locate(/obj/structure/table/, M.loc) && M.lying) && prob(50) ) ) - return ..() + if(borer) + borer.detatch() //Should remove borer if the brain is removed - RR - var/mob/living/carbon/human/H = M - if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - // you can't stab someone in the eyes wearing a mask! - user << "\blue You're going to need to remove their head cover first." - return + var/mob/living/carbon/human/H = target + var/obj/item/organ/brain/B = src + if(istype(B) && istype(H)) + B.transfer_identity(target) -//since these people will be dead M != usr +/obj/item/organ/brain/replaced(var/mob/living/target) - if(M:brain_op_stage == 4.0) - for(var/mob/O in viewers(M, null)) - if(O == (user || M)) - continue - if(M == user) - O.show_message(text("\red [user] inserts [src] into his head!"), 1) - else - O.show_message(text("\red [M] has [src] inserted into his head by [user]."), 1) - - if(M != user) - M << "\red [user] inserts [src] into your head!" - user << "\red You insert [src] into [M]'s head!" - else - user << "\red You insert [src] into your head!" - - //this might actually be outdated since barring badminnery, a debrain'd body will have any client sucked out to the brain's internal mob. Leaving it anyway to be safe. --NEO - if(M.key)//Revised. /N - M.ghostize() + if(target.key) + target.ghostize() + if(brainmob) if(brainmob.mind) - brainmob.mind.transfer_to(M) + brainmob.mind.transfer_to(target) else - M.key = brainmob.key - - M:brain_op_stage = 3.0 - - del(src) - else - ..() - return + target.key = brainmob.key \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm index 62916d818da..897b03c8a14 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/carbon/brain/death.dm @@ -36,7 +36,7 @@ if(container && istype(container, /obj/item/device/mmi)) del(container)//Gets rid of the MMI if there is one if(loc) - if(istype(loc,/obj/item/brain)) + if(istype(loc,/obj/item/organ/brain)) del(loc)//Gets rid of the brain item spawn(15) if(animation) del(animation) diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 6877ed4b854..5ee424bd8db 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -10,7 +10,6 @@ construction_time = 75 var/searching = 0 var/askDelay = 10 * 60 * 1 - mob/living/carbon/brain/brainmob = null req_access = list(access_robotics) locked = 0 mecha = null//This does not appear to be used outside of reference in mecha.dm. @@ -136,7 +135,6 @@ src.brainmob.robot_talk_understand = 1 src.brainmob.stat = 0 src.brainmob.silent = 0 - src.brainmob.brain_op_stage = 4.0 dead_mob_list -= src.brainmob ..() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 0dff048d004..feed242bef0 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -1,7 +1,6 @@ /mob/living/carbon/ gender = MALE var/list/stomach_contents = list() - var/brain_op_stage = 0.0 var/list/datum/disease2/disease/virus2 = list() var/antibodies = 0 var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 2a9850171e7..c672950a18b 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -240,10 +240,11 @@ if(getBrainLoss() >= 60) msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" - if(!key && brain_op_stage != 4 && stat != DEAD) - msg += "[t_He] [t_is] fast asleep. It doesn't look like they are waking up anytime soon.\n" - else if(!client && brain_op_stage != 4 && stat != DEAD) - msg += "[t_He] [t_has] suddenly fallen asleep.\n" + if(has_brain() && stat != DEAD) + if(!key) + msg += "[t_He] [t_is] fast asleep. It doesn't look like they are waking up anytime soon.\n" + else if(!client) + msg += "[t_He] [t_has] suddenly fallen asleep.\n" var/list/wound_flavor_text = list() var/list/is_destroyed = list() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b250884e9f7..3f7faeac8e6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -535,13 +535,13 @@ //Now checks siemens_coefficient of the affected area by default /mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/base_siemens_coeff = 1.0, var/def_zone = null) if(status_flags & GODMODE) return 0 //godmode - + if (!def_zone) def_zone = pick("l_hand", "r_hand") - + var/datum/organ/external/affected_organ = get_organ(check_zone(def_zone)) var/siemens_coeff = base_siemens_coeff * get_siemens_coefficient_organ(affected_organ) - + return ..(shock_damage, source, siemens_coeff, def_zone) @@ -1135,12 +1135,12 @@ /mob/living/carbon/human/proc/is_lung_ruptured() var/datum/organ/internal/lungs/L = internal_organs_by_name["lungs"] - return L.is_bruised() + return L && L.is_bruised() /mob/living/carbon/human/proc/rupture_lung() var/datum/organ/internal/lungs/L = internal_organs_by_name["lungs"] - if(!L.is_bruised()) + if(L && !L.is_bruised()) src.custom_pain("You feel a stabbing pain in your chest!", 1) L.damage = L.min_bruised_damage @@ -1300,6 +1300,7 @@ spawn(0) update_icons() + fixblood() if(species) return 1 @@ -1567,3 +1568,17 @@ flavor_text += flavor_texts[T] flavor_text += "\n\n" return ..() + +/mob/living/carbon/human/has_brain() + if(internal_organs_by_name["brain"]) + var/datum/organ/internal/brain = internal_organs_by_name["brain"] + if(brain && istype(brain)) + return 1 + return 0 + +/mob/living/carbon/human/has_eyes() + if(internal_organs_by_name["eyes"]) + var/datum/organ/internal/eyes = internal_organs_by_name["eyes"] + if(eyes && istype(eyes) && !eyes.status & ORGAN_CUT_AWAY) + return 1 + return 0 diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 01caff57e5a..8b4e010d4b5 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -17,13 +17,19 @@ /mob/living/carbon/human/getBrainLoss() var/res = brainloss - var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] - if (sponge.is_bruised()) - res += 20 - if (sponge.is_broken()) - res += 50 - res = min(res,maxHealth*2) - return res + if(species && species.has_organ["brain"]) + var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] + if(!sponge) + res += 200 + else + if (sponge.is_bruised()) + res += 20 + if (sponge.is_broken()) + res += 50 + + res = min(res,maxHealth*2) + return res + return 0 //These procs fetch a cumulative total damage from all organs /mob/living/carbon/human/getBruteLoss() @@ -264,20 +270,20 @@ This function restores all organs. /mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) //visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]") - + //Handle other types of damage if((damagetype != BRUTE) && (damagetype != BURN)) if(damagetype == HALLOSS) if ((damage > 25 && prob(20)) || (damage > 50 && prob(60))) emote("scream") - - + + ..(damage, damagetype, def_zone, blocked) return 1 //Handle BRUTE and BURN damage handle_suit_punctures(damagetype, damage) - + if(blocked >= 2) return 0 var/datum/organ/external/organ = null diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index c5fb663116a..dd02d3c17d7 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -95,6 +95,9 @@ //Disabilities handle_disabilities() + //Organ failure. + handle_organs() + //Random events (vomiting etc) handle_random_events() @@ -1081,7 +1084,7 @@ handle_organs() //Optimized. handle_blood() - if(health <= config.health_threshold_dead || brain_op_stage == 4.0) + if(health <= config.health_threshold_dead || !has_brain()) death() blinded = 1 silent = 0 @@ -1160,15 +1163,23 @@ //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 + if(!species.has_organ["eyes"]) // Presumably if a species has no eyes, they see via something else. + eye_blind = 0 + blinded = 0 + eye_blurry = 0 + else if(!has_eyes()) // Eyes cut out? Permablind. + eye_blind = 1 + blinded = 1 + eye_blurry = 1 + else if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own + blinded = 1 + else if(eye_blind) // Blindness, heals slowly over time + eye_blind = max(eye_blind-1,0) + blinded = 1 else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster eye_blurry = max(eye_blurry-3, 0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly + blinded = 1 + else if(eye_blurry) // Blurry eyes heal slowly eye_blurry = max(eye_blurry-1, 0) //Ears diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index 67f0b904ed4..85fdb33a8da 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -51,6 +51,8 @@ var/coretype = /obj/item/slime_extract/grey var/list/slime_mutation[4] + var/core_removal_stage = 0 //For removing cores. + /mob/living/carbon/slime/New() create_reagents(100) spawn (0) @@ -984,6 +986,9 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 if(A) G << "Golem rune created in [A.name]." +/mob/living/carbon/slime/has_eyes() + return 0 + //////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them//////////////////////// /* diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index ce681063582..44a7e7a2593 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -485,7 +485,7 @@ silent = 0 else //ALIVE. LIGHTS ARE ON updatehealth() - if(health < config.health_threshold_dead || brain_op_stage == 4.0) + if(health < config.health_threshold_dead || !has_brain()) death() blinded = 1 stat = DEAD diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm index 286bffb3a0f..d5e8a167614 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/species.dm @@ -54,6 +54,15 @@ var/race_key = 0 var/icon/icon_template + var/list/has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "liver" = /datum/organ/internal/liver, + "kidneys" = /datum/organ/internal/kidney, + "brain" = /datum/organ/internal/brain, + "appendix" = /datum/organ/internal/appendix, + "eyes" = /datum/organ/internal/eyes + ) /datum/species/New() unarmed = new unarmed_type() @@ -73,12 +82,9 @@ H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"]) H.internal_organs = list() - H.internal_organs_by_name["heart"] = new/datum/organ/internal/heart(H) - H.internal_organs_by_name["lungs"] = new/datum/organ/internal/lungs(H) - H.internal_organs_by_name["liver"] = new/datum/organ/internal/liver(H) - H.internal_organs_by_name["kidney"] = new/datum/organ/internal/kidney(H) - H.internal_organs_by_name["brain"] = new/datum/organ/internal/brain(H) - H.internal_organs_by_name["eyes"] = new/datum/organ/internal/eyes(H) + for(var/organ in has_organ) + var/organ_type = has_organ[organ] + H.internal_organs_by_name[organ] = new organ_type(H) for(var/name in H.organs_by_name) H.organs += H.organs_by_name[name] diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index daf0e370049..a4e5e0586fd 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -784,3 +784,9 @@ var/area/new_area = get_area(loc) if(new_area) new_area.Entered(src) + +/mob/living/proc/has_brain() + return 1 + +/mob/living/proc/has_eyes() + return 1 \ No newline at end of file diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 3a691d9d353..38feee53e28 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -30,8 +30,9 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 /mob/living/carbon/human/proc/fixblood() for(var/datum/reagent/blood/B in vessel.reagent_list) if(B.id == "blood") - B.data = list( "donor"=src,"viruses"=null,"blood_DNA"=dna.unique_enzymes,"blood_type"=dna.b_type, \ + B.data = list( "donor"=src,"viruses"=null,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.blood_color,"blood_type"=dna.b_type, \ "resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = null) + B.color = B.data["blood_color"] // Takes care blood loss and regeneration /mob/living/carbon/human/proc/handle_blood() @@ -63,14 +64,17 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 // Damaged heart virtually reduces the blood volume, as the blood isn't // being pumped properly anymore. - var/datum/organ/internal/heart/heart = internal_organs_by_name["heart"] + if(species && species.has_organ["heart"]) + var/datum/organ/internal/heart/heart = internal_organs_by_name["heart"] - if(heart.damage > 1 && heart.damage < heart.min_bruised_damage) - blood_volume *= 0.8 - else if(heart.damage >= heart.min_bruised_damage && heart.damage < heart.min_broken_damage) - blood_volume *= 0.6 - else if(heart.damage >= heart.min_broken_damage && heart.damage < INFINITY) - blood_volume *= 0.3 + if(!heart) + blood_volume = 0 + else if(heart.damage > 1 && heart.damage < heart.min_bruised_damage) + blood_volume *= 0.8 + else if(heart.damage >= heart.min_bruised_damage && heart.damage < heart.min_broken_damage) + blood_volume *= 0.6 + else if(heart.damage >= heart.min_broken_damage && heart.damage < INFINITY) + blood_volume *= 0.3 //Effects of bloodloss switch(blood_volume) @@ -141,31 +145,8 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 if(!amt) return - var/turf/T = get_turf(src) - var/list/obj/effect/decal/cleanable/blood/drip/nums = list() - var/list/iconL = list("1","2","3","4","5") - vessel.remove_reagent("blood",amt) - - for(var/obj/effect/decal/cleanable/blood/drip/G in T) - nums += G - iconL.Remove(G.icon_state) - - if (nums.len < 5) - var/obj/effect/decal/cleanable/blood/drip/this = new(T) - this.icon_state = pick(iconL) - this.blood_DNA = list() - this.blood_DNA[dna.unique_enzymes] = dna.b_type - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - this.virus2[ID] = V.getcopy() - if (species) this.basecolor = species.blood_color - this.update_icon() - - else - for(var/obj/effect/decal/cleanable/blood/drip/G in nums) - del G - T.add_blood(src) + blood_splatter(src,src) /**************************************************** BLOOD TRANSFERS @@ -193,6 +174,12 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 B.data["resistances"] = src.resistances.Copy() B.data["blood_type"] = copytext(src.dna.b_type,1,0) + // Putting this here due to return shenanigans. + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + B.data["blood_colour"] = H.species.blood_color + B.color = B.data["blood_colour"] + var/list/temp_chem = list() for(var/datum/reagent/R in src.reagents.reagent_list) temp_chem += R.id @@ -279,4 +266,71 @@ proc/blood_incompatible(donor,receiver) if("O") if(donor_antigen != "O") return 1 //AB is a universal receiver. - return 0 \ No newline at end of file + return 0 + +proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large) + + var/obj/effect/decal/cleanable/blood/B + var/decal_type = /obj/effect/decal/cleanable/blood/splatter + var/turf/T = get_turf(target) + + if(istype(source,/mob/living/carbon/human)) + var/mob/living/carbon/human/M = source + source = M.get_blood(M.vessel) + else if(istype(source,/mob/living/carbon/monkey)) + var/mob/living/carbon/monkey/donor = source + if(donor.dna) + source = new() + source.data["blood_DNA"] = donor.dna.unique_enzymes + source.data["blood_type"] = donor.dna.b_type + + // Are we dripping or splattering? + if(!large) + + // Only a certain number of drips can be on a given turf. + var/list/drips = list() + var/list/drip_icons = list("1","2","3","4","5") + + for(var/obj/effect/decal/cleanable/blood/drip/drop in T) + drips += drop + drip_icons.Remove(drop.icon_state) + + // If we have too many drips, remove them and spawn a proper blood splatter. + if(drips.len >= 5) + //TODO: copy all virus data from drips to new splatter? + for(var/obj/effect/decal/cleanable/blood/drip/drop in drips) + del drop + else + decal_type = /obj/effect/decal/cleanable/blood/drip + + // Find a blood decal or create a new one. + B = locate(decal_type) in T + if(!B) + B = new decal_type(T) + + // If there's no data to copy, call it quits here. + if(!source) + return B + + // Update appearance. + if(source.data["blood_colour"]) + B.basecolor = source.data["blood_colour"] + B.update_icon() + + // Update blood information. + if(source.data["blood_DNA"]) + B.blood_DNA = list() + if(source.data["blood_type"]) + B.blood_DNA[source.data["blood_DNA"]] = source.data["blood_type"] + else + B.blood_DNA[source.data["blood_DNA"]] = "O+" + + // Update virus information. //Looks like this is out of date. + //for(var/datum/disease/D in source.data["viruses"]) + // var/datum/disease/new_virus = D.Copy(1) + // source.viruses += new_virus + // new_virus.holder = B + if(source.data["virus2"]) + B.virus2 = virus_copylist(source.data["virus2"]) + + return B \ No newline at end of file diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index f0c28d87c3b..12b180fd546 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -1,6 +1,8 @@ /datum/organ var/name = "organ" var/mob/living/carbon/human/owner = null + var/status = 0 + var/vital //Lose a vital limb, die immediately. var/list/datum/autopsy_data/autopsy_data = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, @@ -56,6 +58,7 @@ // Takes care of organ related updates, such as broken and missing limbs /mob/living/carbon/human/proc/handle_organs() + number_wounds = 0 var/leg_tally = 2 var/force_process = 0 @@ -72,6 +75,19 @@ for(var/datum/organ/internal/I in internal_organs) I.process() + // Also handles some internal organ processing when the organs are missing completely. + // Only handles missing liver and kidneys for now. + // This is a bit harsh, but really if you're missing an entire bodily organ you're in deep shit. + if(species.has_organ["liver"]) + var/datum/organ/internal/liver = internal_organs_by_name["liver"] + if(!liver || liver.status & ORGAN_CUT_AWAY) + reagents.add_reagent("toxin", rand(1,3)) + + if(species.has_organ["kidneys"]) + var/datum/organ/internal/kidney = internal_organs_by_name["kidneys"] + if(!kidney || kidney.status & ORGAN_CUT_AWAY) + reagents.add_reagent("toxin", rand(1,3)) + if(!force_process && !bad_external_organs.len) return diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 79bbe771b30..c4df67cc870 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -32,12 +32,11 @@ var/damage_msg = "\red You feel an intense pain" var/broken_description - var/vital //Lose a vital limb, die immediately. - var/status = 0 var/open = 0 var/stage = 0 var/cavity = 0 - var/sabotaged = 0 //If a prosthetic limb is emagged, it will detonate when it fails. + var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails. + var/encased // Needs to be opened with a saw to access the organs. var/obj/item/hidden = null var/list/implants = list() @@ -855,6 +854,7 @@ Note that amputating the affected organ does in fact remove the infection from t min_broken_damage = 40 body_part = UPPER_TORSO vital = 1 + encased = "ribcage" /datum/organ/external/groin name = "groin" @@ -958,6 +958,7 @@ Note that amputating the affected organ does in fact remove the infection from t body_part = HEAD var/disfigured = 0 vital = 1 + encased = "skull" /datum/organ/external/head/get_icon(var/icon/race_icon, var/icon/deform_icon) if (!owner) @@ -1062,6 +1063,7 @@ obj/item/weapon/organ/r_hand obj/item/weapon/organ/r_leg name = "right leg" icon_state = "r_leg" + obj/item/weapon/organ/head name = "head" icon_state = "head_m" @@ -1158,11 +1160,12 @@ obj/item/weapon/organ/head/attackby(obj/item/weapon/W as obj, mob/user as mob) brainmob.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)])" msg_admin_attack("[user] ([user.ckey]) debrained [brainmob] ([brainmob.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)") + //TODO: ORGAN REMOVAL UPDATE. if(istype(src,/obj/item/weapon/organ/head/posi)) var/obj/item/device/mmi/posibrain/B = new(loc) B.transfer_identity(brainmob) else - var/obj/item/brain/B = new(loc) + var/obj/item/organ/brain/B = new(loc) B.transfer_identity(brainmob) brain_op_stage = 4.0 diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index 4ed10047564..e8c7acbfbf0 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -10,6 +10,9 @@ var/min_broken_damage = 30 var/parent_organ = "chest" var/robotic = 0 //For being a robot + var/removed_type //When removed, forms this object. + var/list/transplant_data // Blood DNA and colour of donor + var/rejecting // Is this organ already being rejected? /datum/organ/internal/proc/rejuvenate() damage=0 @@ -20,20 +23,19 @@ /datum/organ/internal/proc/is_broken() return damage >= min_broken_damage - - /datum/organ/internal/New(mob/living/carbon/human/H) ..() - var/datum/organ/external/E = H.organs_by_name[src.parent_organ] - if(E.internal_organs == null) - E.internal_organs = list() - E.internal_organs |= src - H.internal_organs |= src - src.owner = H + if(H) + var/datum/organ/external/E = H.organs_by_name[src.parent_organ] + if(E.internal_organs == null) + E.internal_organs = list() + E.internal_organs |= src + H.internal_organs |= src + src.owner = H /datum/organ/internal/process() - //Process infections + //Process infections if (robotic >= 2 || (owner.species && owner.species.flags & IS_PLANT)) //TODO make robotic internal and external organs separate types of organ instead of a flag germ_level = 0 return @@ -44,10 +46,10 @@ //** Handle the effects of infections var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") - + if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30)) germ_level-- - + if (germ_level >= INFECTION_LEVEL_ONE/2) //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes if(antibiotics < 5 && prob(round(germ_level/6))) @@ -58,10 +60,33 @@ //spread germs if (antibiotics < 5 && parent.germ_level < germ_level && ( parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30) )) parent.germ_level++ - + if (prob(3)) //about once every 30 seconds take_damage(1,silent=prob(30)) + // Process unsuitable transplants. TODO: consider some kind of + // immunosuppressant that changes transplant data to make it match. + if(transplant_data) + if(!rejecting) //Should this transplant reject? + if(owner.species != transplant_data["species"]) //Nope. + rejecting = 1 + else if(prob(20) && owner.dna && blood_incompatible(transplant_data["blood_type"],owner.dna.b_type)) + rejecting = 1 + else + rejecting++ //Rejection severity increases over time. + if(rejecting % 10 == 0) //Only fire every ten rejection ticks. + switch(rejecting) + if(1 to 50) + take_damage(rand(1,2)) + if(51 to 200) + take_damage(rand(2,3)) + if(201 to 500) + take_damage(rand(3,4)) + owner.reagents.add_reagent("toxin", 1) + if(501 to INFINITY) + take_damage(5) + owner.reagents.add_reagent("toxin", rand(3,5)) + /datum/organ/internal/proc/take_damage(amount, var/silent=0) if(src.robotic == 2) src.damage += (amount * 0.8) @@ -111,21 +136,22 @@ INTERNAL ORGANS DEFINES ****************************************************/ -/datum/organ/internal/heart +/datum/organ/internal/heart // This is not set to vital because death immediately occurs in blood.dm if it is removed. name = "heart" parent_organ = "chest" - + removed_type = /obj/item/organ/heart /datum/organ/internal/lungs name = "lungs" parent_organ = "chest" + removed_type = /obj/item/organ/lungs process() ..() if (germ_level > INFECTION_LEVEL_ONE) if(prob(5)) owner.emote("cough") //respitory tract infection - + if(is_bruised()) if(prob(2)) spawn owner.emote("me", 1, "coughs up blood!") @@ -138,6 +164,7 @@ name = "liver" parent_organ = "chest" var/process_accuracy = 10 + removed_type = /obj/item/organ/liver process() ..() @@ -147,7 +174,7 @@ if (germ_level > INFECTION_LEVEL_TWO) if(prob(1)) spawn owner.vomit() - + if(owner.life_tick % process_accuracy == 0) if(src.damage < 0) src.damage = 0 @@ -178,16 +205,20 @@ owner.adjustToxLoss(0.3 * process_accuracy) /datum/organ/internal/kidney - name = "kidney" - parent_organ = "chest" + name = "kidneys" + parent_organ = "groin" + removed_type = /obj/item/organ/kidneys /datum/organ/internal/brain name = "brain" parent_organ = "head" + removed_type = /obj/item/organ/brain + vital = 1 /datum/organ/internal/eyes name = "eyes" parent_organ = "head" + removed_type = /obj/item/organ/eyes process() //Eye damage replaces the old eye_stat var. ..() @@ -195,3 +226,20 @@ owner.eye_blurry = 20 if(is_broken()) owner.eye_blind = 20 + +/datum/organ/internal/appendix + name = "appendix" + parent_organ = "groin" + removed_type = /obj/item/organ/appendix + +/datum/organ/internal/proc/remove(var/mob/user) + + if(!removed_type) return 0 + + var/obj/item/organ/removed_organ = new removed_type(get_turf(user)) + + if(istype(removed_organ)) + removed_organ.organ_data = src + removed_organ.update() + + return removed_organ \ No newline at end of file diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm new file mode 100644 index 00000000000..c48a9d4b541 --- /dev/null +++ b/code/modules/organs/organ_objects.dm @@ -0,0 +1,232 @@ +/obj/item/organ + name = "organ" + desc = "It looks like it probably just plopped out." + icon = 'icons/obj/surgery.dmi' + icon_state = "appendix" + + health = 100 // Process() ticks before death. + + var/fresh = 3 // Squirts of blood left in it. + var/dead_icon // Icon used when the organ dies. + var/robotic // Is the limb prosthetic? + var/organ_tag // What slot does it go in? + var/organ_type = /datum/organ/internal // Used to spawn the relevant organ data when produced via a machine or spawn(). + var/datum/organ/internal/organ_data // Stores info when removed. + var/prosthetic_name = "prosthetic organ" // Flavour string for robotic organ. + var/prosthetic_icon // Icon for robotic organ. + +/obj/item/organ/attack_self(mob/user as mob) + + // Convert it to an edible form, yum yum. + if(!robotic && user.a_intent == "help" && user.zone_sel.selecting == "mouth") + bitten(user) + return + +/obj/item/organ/New() + ..() + create_reagents(5) + if(!robotic) + processing_objects += src + spawn(1) + update() + +/obj/item/organ/Del() + if(!robotic) processing_objects -= src + ..() + +/obj/item/organ/process() + + if(robotic) + processing_objects -= src + return + + // Don't process if we're in a freezer, an MMI or a stasis bag. //TODO: ambient temperature? + if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer)) + return + + if(fresh && prob(40)) + fresh-- + var/datum/reagent/blood = reagents.reagent_list["blood"] + blood_splatter(src,blood,1) + + health -= rand(1,3) + if(health <= 0) + die() + +/obj/item/organ/proc/die() + name = "dead [initial(name)]" + if(dead_icon) icon_state = dead_icon + health = 0 + processing_objects -= src + //TODO: Grey out the icon state. + //TODO: Inject an organ with peridaxon to make it alive again. + +/obj/item/organ/proc/roboticize() + + robotic = (organ_data && organ_data.robotic) ? organ_data.robotic : 1 + + if(prosthetic_name) + name = prosthetic_name + + if(prosthetic_icon) + icon_state = prosthetic_icon + else + //TODO: convert to greyscale. + +/obj/item/organ/proc/update() + + if(!organ_data) + organ_data = new /datum/organ/internal() + + if(robotic) + organ_data.robotic = robotic + + if(organ_data.robotic >= 2) + roboticize() + +// Brain is defined in brain_item.dm. +/obj/item/organ/heart + name = "heart" + icon_state = "heart-on" + prosthetic_name = "circulatory pump" + prosthetic_icon = "heart-prosthetic" + organ_tag = "heart" + fresh = 6 // Juicy. + dead_icon = "heart-off" + +/obj/item/organ/lungs + name = "lungs" + icon_state = "lungs" + prosthetic_name = "gas exchange system" + prosthetic_icon = "lungs-prosthetic" + organ_tag = "lungs" + +/obj/item/organ/kidneys + name = "kidneys" + icon_state = "kidneys" + prosthetic_name = "prosthetic kidneys" + prosthetic_icon = "kidneys-prosthetic" + organ_tag = "kidneys" + +/obj/item/organ/eyes + name = "eyeballs" + icon_state = "eyes" + prosthetic_name = "visual prosthesis" + prosthetic_icon = "eyes-prosthetic" + organ_tag = "eyes" + + var/eye_colour + +/obj/item/organ/liver + name = "liver" + icon_state = "liver" + prosthetic_name = "toxin filter" + prosthetic_icon = "liver-prosthetic" + organ_tag = "liver" + +/obj/item/organ/appendix + name = "appendix" + icon_state = "appendix" + organ_tag = "appendix" + +//These are here so they can be printed out via the fabricator. +/obj/item/organ/heart/prosthetic + robotic = 2 + +/obj/item/organ/lungs/prosthetic + robotic = 2 + +/obj/item/organ/kidneys/prosthetic + robotic = 2 + +/obj/item/organ/eyes/prosthetic + robotic = 2 + +/obj/item/organ/liver/prosthetic + robotic = 2 + +/obj/item/organ/appendix + name = "appendix" + +/obj/item/organ/proc/removed(var/mob/living/target,var/mob/living/user) + + if(!target || !user) + return + + if(organ_data.vital) + user.attack_log += "\[[time_stamp()]\] removed a vital organ ([src]) from [target.name] ([target.ckey]) (INTENT: [uppertext(user.a_intent)])" + target.attack_log += "\[[time_stamp()]\] had a vital organ ([src]) removed by [user.name] ([user.ckey]) (INTENT: [uppertext(user.a_intent)])" + msg_admin_attack("[user.name] ([user.ckey]) removed a vital organ ([src]) from [target.name] ([target.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)") + target.death() + +/obj/item/organ/appendix/removed(var/mob/living/target,var/mob/living/user) + + ..() + + var/inflamed = 0 + for(var/datum/disease/appendicitis/appendicitis in target.viruses) + inflamed = 1 + appendicitis.cure() + target.resistances += appendicitis + + if(inflamed) + icon_state = "appendixinflamed" + name = "inflamed appendix" + +/obj/item/organ/eyes/removed(var/mob/living/target,var/mob/living/user) + + if(!eye_colour) + eye_colour = list(0,0,0) + + ..() //Make sure target is set so we can steal their eye colour for later. + var/mob/living/carbon/human/H = target + if(istype(H)) + eye_colour = list( + H.r_eyes ? H.r_eyes : 0, + H.g_eyes ? H.g_eyes : 0, + H.b_eyes ? H.b_eyes : 0 + ) + + // Leave bloody red pits behind! + H.r_eyes = 128 + H.g_eyes = 0 + H.b_eyes = 0 + H.update_body() + +/obj/item/organ/proc/replaced(var/mob/living/target) + return + +/obj/item/organ/eyes/replaced(var/mob/living/target) + + // Apply our eye colour to the target. + var/mob/living/carbon/human/H = target + if(istype(H) && eye_colour) + H.r_eyes = eye_colour[1] + H.g_eyes = eye_colour[2] + H.b_eyes = eye_colour[3] + H.update_body() + +/obj/item/organ/proc/bitten(mob/user) + + if(robotic) + return + + user << "\blue You take an experimental bite out of \the [src]." + var/datum/reagent/blood = reagents.reagent_list["blood"] + blood_splatter(src,blood,1) + + + user.drop_from_inventory(src) + var/obj/item/weapon/reagent_containers/food/snacks/organ/O = new(get_turf(src)) + O.name = name + O.icon_state = dead_icon ? dead_icon : icon_state + + // Pass over the blood. + reagents.trans_to(O, reagents.total_volume) + + if(fingerprints) O.fingerprints = fingerprints.Copy() + if(fingerprintshidden) O.fingerprintshidden = fingerprintshidden.Copy() + if(fingerprintslast) O.fingerprintslast = fingerprintslast + + user.put_in_active_hand(O) + del(src) \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index b1858cd6987..13962c71346 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -95,7 +95,7 @@ datum blood - data = new/list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null, "antibodies" = null) + data = new/list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"blood_colour"= "#A10808","resistances"=null,"trace_chem"=null, "antibodies" = null) name = "Blood" id = "blood" reagent_state = LIQUID @@ -128,49 +128,30 @@ datum var/mob/living/carbon/C = M C.antibodies |= self.data["antibodies"] + on_merge(var/data) + if(data["blood_colour"]) + color = data["blood_colour"] + return ..() - + on_update(var/atom/A) + if(data["blood_colour"]) + color = data["blood_colour"] + return ..() reaction_turf(var/turf/simulated/T, var/volume)//splash the blood all over the place if(!istype(T)) return var/datum/reagent/blood/self = src src = null if(!(volume >= 3)) return - //var/datum/disease/D = self.data["virus"] + if(!self.data["donor"] || istype(self.data["donor"], /mob/living/carbon/human)) - var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T //find some blood here - if(!blood_prop) //first blood! - blood_prop = new(T) - blood_prop.blood_DNA[self.data["blood_DNA"]] = self.data["blood_type"] - - for(var/datum/disease/D in self.data["viruses"]) - var/datum/disease/newVirus = D.Copy(1) - blood_prop.viruses += newVirus - newVirus.holder = blood_prop - - if(self.data["virus2"]) - blood_prop.virus2 = virus_copylist(self.data["virus2"]) - - + blood_splatter(T,self,1) else if(istype(self.data["donor"], /mob/living/carbon/monkey)) - var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T - if(!blood_prop) - blood_prop = new(T) - blood_prop.blood_DNA["Non-Human DNA"] = "A+" - for(var/datum/disease/D in self.data["viruses"]) - var/datum/disease/newVirus = D.Copy(1) - blood_prop.viruses += newVirus - newVirus.holder = blood_prop - + var/obj/effect/decal/cleanable/blood/B = blood_splatter(T,self,1) + if(B) B.blood_DNA["Non-Human DNA"] = "A+" else if(istype(self.data["donor"], /mob/living/carbon/alien)) - var/obj/effect/decal/cleanable/blood/xeno/blood_prop = locate() in T - if(!blood_prop) - blood_prop = new(T) - blood_prop.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*" - for(var/datum/disease/D in self.data["viruses"]) - var/datum/disease/newVirus = D.Copy(1) - blood_prop.viruses += newVirus - newVirus.holder = blood_prop + var/obj/effect/decal/cleanable/blood/B = blood_splatter(T,self,1) + if(B) B.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*" return /* Must check the transfering of reagents and their data first. They all can point to one disease datum. @@ -1276,7 +1257,7 @@ datum if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if(istype(E)) + if(E && istype(E)) if(E.damage > 0) E.damage = max(E.damage - 1, 0) ..() @@ -3024,7 +3005,9 @@ datum if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/liver/L = H.internal_organs_by_name["liver"] - if (istype(L)) + if (!L) + H.adjustToxLoss(5) + else if(istype(L)) L.take_damage(0.1, 1) H.adjustToxLoss(0.1) ..() @@ -3264,13 +3247,13 @@ datum if(prob(5)) if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/heart/L = H.internal_organs_by_name["heart"] - if (istype(L)) + if (L && istype(L)) L.take_damage(5, 0) if (300 to INFINITY) if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/heart/L = H.internal_organs_by_name["heart"] - if (istype(L)) + if (L && istype(L)) L.take_damage(100, 0) holder.remove_reagent(src.id, FOOD_METABOLISM) diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 29001d9723f..28e369f531f 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -590,25 +590,20 @@ ..() reagents.add_reagent("nutriment", 1) -/obj/item/weapon/reagent_containers/food/snacks/appendix -//yes, this is the same as meat. I might do something different in future - name = "appendix" - desc = "An appendix which looks perfectly healthy." +/obj/item/weapon/reagent_containers/food/snacks/organ + + name = "organ" + desc = "It's good for you." icon = 'icons/obj/surgery.dmi' icon_state = "appendix" filling_color = "#E00D34" New() ..() - reagents.add_reagent("nutriment", 3) + reagents.add_reagent("nutriment", rand(3,5)) + reagents.add_reagent("toxin", rand(1,3)) src.bitesize = 3 -/obj/item/weapon/reagent_containers/food/snacks/appendix/inflamed - name = "inflamed appendix" - desc = "An appendix which appears to be inflamed." - icon_state = "appendixinflamed" - filling_color = "#E00D7A" - /obj/item/weapon/reagent_containers/food/snacks/tofu name = "Tofu" icon_state = "tofu" @@ -1559,7 +1554,6 @@ On_Consume(var/mob/M) M << "Something inside of you suddently expands!" - if (istype(M, /mob/living/carbon/human)) //Do not try to understand. var/obj/item/weapon/surprise = new/obj/item/weapon(M) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 5e6277c8e7c..5617a3802e6 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -128,7 +128,7 @@ if(SYRINGE_INJECT) if(!reagents.total_volume) - user << "\red The Syringe is empty." + user << "\red The syringe is empty." return if(istype(target, /obj/item/weapon/implantcase/chem)) return diff --git a/code/modules/surgery/appendix.dm b/code/modules/surgery/appendix.dm deleted file mode 100644 index 91332eab06b..00000000000 --- a/code/modules/surgery/appendix.dm +++ /dev/null @@ -1,89 +0,0 @@ -//Procedures in this file: Appendectomy -////////////////////////////////////////////////////////////////// -// APPENDECTOMY // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/appendectomy/ - priority = 2 - can_infect = 1 - blood_level = 1 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (!hasorgans(target)) - return 0 - if (target_zone != "groin") - return 0 - var/datum/organ/external/groin = target.get_organ("groin") - if (!groin) - return 0 - if (groin.open < 2) - return 0 - return 1 - -/datum/surgery_step/appendectomy/cut_appendix - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 70 - max_duration = 90 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.appendix == 0 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts to separate [target]'s appendix from the abdominal wall with \the [tool].", \ - "You start to separate [target]'s appendix from the abdominal wall with \the [tool]." ) - target.custom_pain("The pain in your abdomen is living hell!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has separated [target]'s appendix with \the [tool]." , \ - "\blue You have separated [target]'s appendix with \the [tool].") - target.op_stage.appendix = 1 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/groin = target.get_organ("groin") - user.visible_message("\red [user]'s hand slips, slicing an artery inside [target]'s abdomen with \the [tool]!", \ - "\red Your hand slips, slicing an artery inside [target]'s abdomen with \the [tool]!") - groin.createwound(CUT, 50, 1) - -/datum/surgery_step/appendectomy/remove_appendix - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - min_duration = 60 - max_duration = 80 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.appendix == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts removing [target]'s appendix with \the [tool].", \ - "You start removing [target]'s appendix with \the [tool].") - target.custom_pain("Someone's ripping out your bowels!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has removed [target]'s appendix with \the [tool].", \ - "\blue You have removed [target]'s appendix with \the [tool].") - var/app = 0 - for(var/datum/disease/appendicitis/appendicitis in target.viruses) - app = 1 - appendicitis.cure() - target.resistances += appendicitis - if (app) - new /obj/item/weapon/reagent_containers/food/snacks/appendix/inflamed(get_turf(target)) - else - new /obj/item/weapon/reagent_containers/food/snacks/appendix(get_turf(target)) - target.op_stage.appendix = 2 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) - user.visible_message("\red [user]'s hand slips, nicking internal organs in [target]'s abdomen with \the [tool]!", \ - "\red Your hand slips, nicking internal organs in [target]'s abdomen with \the [tool]!") - affected.createwound(BRUISE, 20) diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index 0bc14075677..605b1503d56 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -18,7 +18,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && affected.stage == 0 + return affected.open >= 2 && affected.stage == 0 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -52,7 +52,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.name != "head" && affected.open == 2 && affected.stage == 1 + return affected.name != "head" && affected.open >= 2 && affected.stage == 1 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -91,7 +91,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.name == "head" && affected.open == 2 && affected.stage == 1 + return affected.name == "head" && affected.open >= 2 && affected.stage == 1 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user] is beginning to piece together [target]'s skull with \the [tool]." , \ @@ -127,7 +127,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && affected.stage == 2 + return affected.open >= 2 && affected.stage == 2 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/surgery/braincore.dm b/code/modules/surgery/braincore.dm deleted file mode 100644 index 4bc804eab5d..00000000000 --- a/code/modules/surgery/braincore.dm +++ /dev/null @@ -1,279 +0,0 @@ -//Procedures in this file: Brain extraction. Brain fixing. Slime Core extraction. -////////////////////////////////////////////////////////////////// -// BRAIN SURGERY // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/brain/ - priority = 2 - blood_level = 1 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return target_zone == "head" && hasorgans(target) - -/datum/surgery_step/brain/saw_skull - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target_zone == "head" && target.brain_op_stage == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] begins to cut through [target]'s skull with \the [tool].", \ - "You begin to cut through [target]'s skull with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has cut [target]'s skull open with \the [tool].", \ - "\blue You have cut [target]'s skull open with \the [tool].") - target.brain_op_stage = 2 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cracking [target]'s skull with \the [tool]!" , \ - "\red Your hand slips, cracking [target]'s skull with \the [tool]!" ) - target.apply_damage(max(10, tool.force), BRUTE, "head") - -/datum/surgery_step/brain/cut_brain - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts separating connections to [target]'s brain with \the [tool].", \ - "You start separating connections to [target]'s brain with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] separates connections to [target]'s brain with \the [tool].", \ - "\blue You separate connections to [target]'s brain with \the [tool].") - target.brain_op_stage = 3 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cutting a vein in [target]'s brain with \the [tool]!", \ - "\red Your hand slips, cutting a vein in [target]'s brain with \the [tool]!") - target.apply_damage(50, BRUTE, "head", 1, sharp=1) - -/datum/surgery_step/brain/saw_spine - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 3 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts separating [target]'s brain from \his spine with \the [tool].", \ - "You start separating [target]'s brain from spine with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] separates [target]'s brain from \his spine with \the [tool].", \ - "\blue You separate [target]'s brain from spine with \the [tool].") - - var/mob/living/simple_animal/borer/borer = target.has_brain_worms() - - if(borer) - borer.detatch() //Should remove borer if the brain is removed - RR - - user.attack_log += "\[[time_stamp()]\] Debrained [target.name] ([target.ckey]) with [tool.name] (INTENT: [uppertext(user.a_intent)])" - target.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [tool.name] (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) debrained [target.name] ([target.ckey]) with [tool.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") - - var/mob/living/carbon/human/H - if(istype(target,/mob/living/carbon/human)) - H = target - - var/obj/item/brain/B - if(H && H.species && H.species.flags & IS_SYNTHETIC) - var/obj/item/device/mmi/posibrain/P = new(target.loc) - P.transfer_identity(target) - else - B = new(target.loc) - B.transfer_identity(target) - - target.internal_organs -= B - target.internal_organs_by_name -= "brain" - - target:brain_op_stage = 4.0 - target.death()//You want them to die after the brain was transferred, so not to trigger client death() twice. - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cutting a vein in [target]'s brain with \the [tool]!", \ - "\red Your hand slips, cutting a vein in [target]'s brain with \the [tool]!") - target.apply_damage(30, BRUTE, "head", 1, sharp=1) - if (ishuman(user)) - user:bloody_body(target) - user:bloody_hands(target, 0) - - -////////////////////////////////////////////////////////////////// -// BRAIN DAMAGE FIXING // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/brain/bone_chips - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts taking bone chips out of [target]'s brain with \the [tool].", \ - "You start taking bone chips out of [target]'s brain with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] takes out all the bone chips in [target]'s brain with \the [tool].", \ - "\blue You take out all the bone chips in [target]'s brain with \the [tool].") - target.brain_op_stage = 3 - - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, jabbing \the [tool] in [target]'s brain!", \ - "\red Your hand slips, jabbing \the [tool] in [target]'s brain!") - target.apply_damage(30, BRUTE, "head", 1, sharp=1) - -/datum/surgery_step/brain/hematoma - allowed_tools = list( - /obj/item/weapon/FixOVein = 100, \ - /obj/item/stack/cable_coil = 75 - ) - - min_duration = 90 - max_duration = 110 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 3 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts mending hematoma in [target]'s brain with \the [tool].", \ - "You start mending hematoma in [target]'s brain with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] mends hematoma in [target]'s brain with \the [tool].", \ - "\blue You mend hematoma in [target]'s brain with \the [tool].") - var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] - if (sponge) - sponge.damage = 0 - - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, bruising [target]'s brain with \the [tool]!", \ - "\red Your hand slips, bruising [target]'s brain with \the [tool]!") - target.apply_damage(20, BRUTE, "head", 1, sharp=1) - -////////////////////////////////////////////////////////////////// -// SLIME CORE EXTRACTION // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/slime - is_valid_target(mob/living/carbon/slime/target) - return istype(target, /mob/living/carbon/slime/) - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return target.stat == 2 - -/datum/surgery_step/slime/cut_flesh - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 30 - max_duration = 50 - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 0 - - begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("[user] starts cutting through [target]'s flesh with \the [tool].", \ - "You start cutting through [target]'s flesh with \the [tool].") - - end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] cuts through [target]'s flesh with \the [tool].", \ - "\blue You cut through [target]'s flesh with \the [tool], revealing its silky innards.") - target.brain_op_stage = 1 - - fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, tearing [target]'s flesh with \the [tool]!", \ - "\red Your hand slips, tearing [target]'s flesh with \the [tool]!") - -/datum/surgery_step/slime/cut_innards - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 30 - max_duration = 50 - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 1 - - begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("[user] starts cutting [target]'s silky innards apart with \the [tool].", \ - "You start cutting [target]'s silky innards apart with \the [tool].") - - end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] cuts [target]'s innards apart with \the [tool], exposing the cores.", \ - "\blue You cut [target]'s innards apart with \the [tool], exposing the cores.") - target.brain_op_stage = 2 - - fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, tearing [target]'s innards with \the [tool]!", \ - "\red Your hand slips, tearing [target]'s innards with \the [tool]!") - -/datum/surgery_step/slime/saw_core - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 2 && target.cores > 0 - - begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("[user] starts cutting out one of [target]'s cores with \the [tool].", \ - "You start cutting out one of [target]'s cores with \the [tool].") - - end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - target.cores-- - user.visible_message("\blue [user] cuts out one of [target]'s cores with \the [tool].",, \ - "\blue You cut out one of [target]'s cores with \the [tool]. [target.cores] cores left.") - - if(target.cores >= 0) - new target.coretype(target.loc) - if(target.cores <= 0) - target.icon_state = "[target.colour] baby slime dead-nocore" - - - fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, causing \him to miss the core!", \ - "\red Your hand slips, causing you to miss the core!") \ No newline at end of file diff --git a/code/modules/surgery/brainrepair.dm b/code/modules/surgery/brainrepair.dm new file mode 100644 index 00000000000..85b5dd8dd3e --- /dev/null +++ b/code/modules/surgery/brainrepair.dm @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////// +// BRAIN DAMAGE FIXING // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/brain/bone_chips + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/weapon/wirecutters = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + priority = 3 + min_duration = 80 + max_duration = 100 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + return (sponge && sponge.damage > 0 && sponge.damage <= 20) && affected.open == 3 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts taking bone chips out of [target]'s brain with \the [tool].", \ + "You start taking bone chips out of [target]'s brain with \the [tool].") + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] takes out all the bone chips in [target]'s brain with \the [tool].", \ + "\blue You take out all the bone chips in [target]'s brain with \the [tool].") + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + if (sponge) + sponge.damage = 0 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, jabbing \the [tool] in [target]'s brain!", \ + "\red Your hand slips, jabbing \the [tool] in [target]'s brain!") + target.apply_damage(30, BRUTE, "head", 1, sharp=1) + +/datum/surgery_step/brain/hematoma + allowed_tools = list( + /obj/item/weapon/FixOVein = 100, \ + /obj/item/stack/cable_coil = 75 + ) + + priority = 3 + min_duration = 90 + max_duration = 110 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + return (sponge && sponge.damage > 20) && affected.open == 3 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts mending hematoma in [target]'s brain with \the [tool].", \ + "You start mending hematoma in [target]'s brain with \the [tool].") + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] mends hematoma in [target]'s brain with \the [tool].", \ + "\blue You mend hematoma in [target]'s brain with \the [tool].") + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + if (sponge) + sponge.damage = 20 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, bruising [target]'s brain with \the [tool]!", \ + "\red Your hand slips, bruising [target]'s brain with \the [tool]!") + target.apply_damage(20, BRUTE, "head", 1, sharp=1) \ No newline at end of file diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm new file mode 100644 index 00000000000..dcd6cc4b318 --- /dev/null +++ b/code/modules/surgery/encased.dm @@ -0,0 +1,220 @@ +//Procedures in this file: Generic ribcage opening steps, Removing alien embryo, Fixing internal organs. +////////////////////////////////////////////////////////////////// +// GENERIC RIBCAGE SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/open_encased + priority = 2 + can_infect = 1 + blood_level = 1 + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return 0 + + var/datum/organ/external/affected = target.get_organ(target_zone) + return affected.encased && affected.open >= 2 + + +/datum/surgery_step/open_encased/saw + allowed_tools = list( + /obj/item/weapon/circular_saw = 100, \ + /obj/item/weapon/hatchet = 75 + ) + + min_duration = 50 + max_duration = 70 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 2 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("[user] begins to cut through [target]'s [affected.encased] with \the [tool].", \ + "You begin to cut through [target]'s [affected.encased] with \the [tool].") + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\blue [user] has cut [target]'s [affected.encased] open with \the [tool].", \ + "\blue You have cut [target]'s [affected.encased] open with \the [tool].") + affected.open = 2.5 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\red [user]'s hand slips, cracking [target]'s [affected.encased] with \the [tool]!" , \ + "\red Your hand slips, cracking [target]'s [affected.encased] with \the [tool]!" ) + + affected.createwound(CUT, 20) + affected.fracture() + + +/datum/surgery_step/open_encased/retract + allowed_tools = list( + /obj/item/weapon/retractor = 100, \ + /obj/item/weapon/crowbar = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + min_duration = 30 + max_duration = 40 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 2.5 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "[user] starts to force open the [affected.encased] in [target]'s [affected.display_name] with \the [tool]." + var/self_msg = "You start to force open the [affected.encased] in [target]'s [affected.display_name] with \the [tool]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\blue [user] forces open [target]'s [affected.encased] with \the [tool]." + var/self_msg = "\blue You force open [target]'s [affected.encased] with \the [tool]." + user.visible_message(msg, self_msg) + + affected.open = 3 + + // Whoops! + if(prob(10)) + affected.fracture() + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\red [user]'s hand slips, cracking [target]'s [affected.encased]!" + var/self_msg = "\red Your hand slips, cracking [target]'s [affected.encased]!" + user.visible_message(msg, self_msg) + + affected.createwound(BRUISE, 20) + affected.fracture() + +/datum/surgery_step/open_encased/close + allowed_tools = list( + /obj/item/weapon/retractor = 100, \ + /obj/item/weapon/crowbar = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + min_duration = 20 + max_duration = 40 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 3 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "[user] starts bending [target]'s [affected.encased] back into place with \the [tool]." + var/self_msg = "You start bending [target]'s [affected.encased] back into place with \the [tool]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\blue [user] bends [target]'s [affected.encased] back into place with \the [tool]." + var/self_msg = "\blue You bend [target]'s [affected.encased] back into place with \the [tool]." + user.visible_message(msg, self_msg) + + affected.open = 2.5 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\red [user]'s hand slips, bending [target]'s [affected.encased] the wrong way!" + var/self_msg = "\red Your hand slips, bending [target]'s [affected.encased] the wrong way!" + user.visible_message(msg, self_msg) + + affected.createwound(BRUISE, 20) + affected.fracture() + + /*if (prob(40)) //TODO: ORGAN REMOVAL UPDATE. + user.visible_message("\red A rib pierces the lung!") + target.rupture_lung()*/ + +/datum/surgery_step/open_encased/mend + allowed_tools = list( + /obj/item/weapon/bonegel = 100, \ + /obj/item/weapon/screwdriver = 75 + ) + + min_duration = 20 + max_duration = 40 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 2.5 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "[user] starts applying \the [tool] to [target]'s [affected.encased]." + var/self_msg = "You start applying \the [tool] to [target]'s [affected.encased]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\blue [user] applied \the [tool] to [target]'s [affected.encased]." + var/self_msg = "\blue You applied \the [tool] to [target]'s [affected.encased]." + user.visible_message(msg, self_msg) + + affected.open = 2 \ No newline at end of file diff --git a/code/modules/surgery/eye.dm b/code/modules/surgery/eye.dm index d142b8ef67c..0fa9f4863a1 100644 --- a/code/modules/surgery/eye.dm +++ b/code/modules/surgery/eye.dm @@ -12,7 +12,10 @@ var/datum/organ/external/affected = target.get_organ(target_zone) if (!affected) return 0 - return target_zone == "eyes" + + var/datum/organ/internal/eyes = target.internal_organs_by_name["eyes"] + + return target_zone == "eyes" && eyes /datum/surgery_step/eye/cut_open allowed_tools = list( diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 94c7b2b861e..a05c6f120b2 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -56,8 +56,6 @@ affected.createwound(CUT, 1) affected.clamp() spread_germs_to_organ(affected, user) - if (target_zone == "head") - target.brain_op_stage = 1 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -95,8 +93,6 @@ affected.createwound(CUT, 1) affected.clamp() affected.open = 2 - if (target_zone == "head") - target.brain_op_stage = 1 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -134,8 +130,6 @@ affected.open = 1 affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) - if (target_zone == "head") - target.brain_op_stage = 1 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -191,7 +185,7 @@ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(..()) var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 1 && !(affected.status & ORGAN_BLEEDING) + return affected.open == 1 //&& !(affected.status & ORGAN_BLEEDING) begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index 57df6a398c6..7e2fbc776e4 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -10,7 +10,7 @@ if(!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && !(affected.status & ORGAN_BLEEDING) && (target_zone != "chest" || target.op_stage.ribcage == 2) + return affected.open == (affected.encased ? 3 : 2) && !(affected.status & ORGAN_BLEEDING) proc/get_max_wclass(datum/organ/external/affected) switch (affected.name) @@ -156,6 +156,10 @@ min_duration = 80 max_duration = 100 + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + return ..() && (!sponge || !sponge.damage) + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts poking around inside the incision on [target]'s [affected.display_name] with \the [tool].", \ diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm new file mode 100644 index 00000000000..87675e906ef --- /dev/null +++ b/code/modules/surgery/organs_internal.dm @@ -0,0 +1,493 @@ +// Internal surgeries. +/datum/surgery_step/internal + priority = 2 + can_infect = 1 + blood_level = 1 + +/datum/surgery_step/internal/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return 0 + + var/datum/organ/external/affected = target.get_organ(target_zone) + return affected.open == (affected.encased ? 3 : 2) + +////////////////////////////////////////////////////////////////// +// ALIEN EMBRYO SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/internal/remove_embryo + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/weapon/wirecutters = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + blood_level = 2 + + min_duration = 80 + max_duration = 100 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/embryo = 0 + for(var/obj/item/alien_embryo/A in target) + embryo = 1 + break + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && embryo && affected.open == 3 && target_zone == "chest" + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/msg = "[user] starts to pull something out from [target]'s ribcage with \the [tool]." + var/self_msg = "You start to pull something out from [target]'s ribcage with \the [tool]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your chest!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user] rips the larva out of [target]'s ribcage!", + "You rip the larva out of [target]'s ribcage!") + + for(var/obj/item/alien_embryo/A in target) + A.loc = A.loc.loc + + +////////////////////////////////////////////////////////////////// +// CHEST INTERNAL ORGAN SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/internal/fix_organ + allowed_tools = list( + /obj/item/stack/medical/advanced/bruise_pack= 100, \ + /obj/item/stack/medical/bruise_pack = 20, \ + /obj/item/stack/medical/bruise_pack/tajaran = 70, \ + ) + + min_duration = 70 + max_duration = 90 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/is_organ_damaged = 0 + for(var/datum/organ/internal/I in affected.internal_organs) + if(I.damage > 0) + is_organ_damaged = 1 + break + return ..() && is_organ_damaged + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/tool_name = "\the [tool]" + if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) + tool_name = "regenerative membrane" + if (istype(tool, /obj/item/stack/medical/bruise_pack)) + if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) + tool_name = "the poultice" + else + tool_name = "the bandaid" + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic < 2) + user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ + "You start treating damage to [target]'s [I.name] with [tool_name]." ) + + target.custom_pain("The pain in your [affected.display_name] is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/tool_name = "\the [tool]" + if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) + tool_name = "regenerative membrane" + if (istype(tool, /obj/item/stack/medical/bruise_pack)) + if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) + tool_name = "the poultice" + else + tool_name = "the bandaid" + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic < 2) + user.visible_message("\blue [user] treats damage to [target]'s [I.name] with [tool_name].", \ + "\blue You treat damage to [target]'s [I.name] with [tool_name]." ) + I.damage = 0 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\red [user]'s hand slips, getting mess and tearing the inside of [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, getting mess and tearing the inside of [target]'s [affected.display_name] with \the [tool]!") + var/dam_amt = 2 + + if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) + target.adjustToxLoss(5) + + else if (istype(tool, /obj/item/stack/medical/bruise_pack)) + if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) + target.adjustToxLoss(7) + else + dam_amt = 5 + target.adjustToxLoss(10) + affected.createwound(CUT, 5) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + I.take_damage(dam_amt,0) + +/datum/surgery_step/internal/fix_organ_robotic //For artificial organs + allowed_tools = list( + /obj/item/stack/nanopaste = 100, \ + /obj/item/weapon/bonegel = 30, \ + /obj/item/weapon/screwdriver = 70, \ + ) + + min_duration = 70 + max_duration = 90 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/is_organ_damaged = 0 + for(var/datum/organ/internal/I in affected.internal_organs) + if(I.damage > 0 && I.robotic >= 2) + is_organ_damaged = 1 + break + return ..() && is_organ_damaged + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic >= 2) + user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \ + "You start mending the damage to [target]'s [I.name]'s mechanisms." ) + + target.custom_pain("The pain in your [affected.display_name] is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + + if(I && I.damage > 0) + if(I.robotic >= 2) + user.visible_message("\blue [user] repairs [target]'s [I.name] with [tool].", \ + "\blue You repair [target]'s [I.name] with [tool]." ) + I.damage = 0 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\red [user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, gumming up the mechanisms inside of [target]'s [affected.display_name] with \the [tool]!") + + target.adjustToxLoss(5) + affected.createwound(CUT, 5) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I) + I.take_damage(rand(3,5),0) + + +/datum/surgery_step/internal/detatch_organ + + allowed_tools = list( + /obj/item/weapon/scalpel = 100, \ + /obj/item/weapon/kitchenknife = 75, \ + /obj/item/weapon/shard = 50, \ + ) + + min_duration = 90 + max_duration = 110 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!..()) + return 0 + + target.op_stage.current_organ = null + + var/list/attached_organs = list() + for(var/organ in target.internal_organs_by_name) + var/datum/organ/internal/I = target.internal_organs_by_name[organ] + if(!I.status && I.parent_organ == target_zone) + attached_organs |= organ + + var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs + if(!organ_to_remove) + return 0 + + target.op_stage.current_organ = organ_to_remove + + return ..() && organ_to_remove + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("[user] starts to separate [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start to separate [target]'s [target.op_stage.current_organ] with \the [tool]." ) + target.custom_pain("The pain in your [affected.display_name] is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] has separated [target]'s [target.op_stage.current_organ] with \the [tool]." , \ + "\blue You have separated [target]'s [target.op_stage.current_organ] with \the [tool].") + + var/datum/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] + if(I && istype(I)) + I.status |= ORGAN_CUT_AWAY + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, slicing an artery inside [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, slicing an artery inside [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(CUT, rand(30,50), 1) + +/datum/surgery_step/internal/remove_organ + + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/weapon/wirecutters = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + min_duration = 60 + max_duration = 80 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!..()) + return 0 + + target.op_stage.current_organ = null + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/datum/organ/internal/I = target.internal_organs_by_name[organ] + if(I.status & ORGAN_CUT_AWAY && I.parent_organ == target_zone) + removable_organs |= organ + + var/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in removable_organs + if(!organ_to_remove) + return 0 + + target.op_stage.current_organ = organ_to_remove + return ..() + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts removing [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start removing [target]'s [target.op_stage.current_organ] with \the [tool].") + target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] has removed [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "\blue You have removed [target]'s [target.op_stage.current_organ] with \the [tool].") + + // Extract the organ! + if(target.op_stage.current_organ) + + var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] + + var/obj/item/organ/O + if(I && istype(I)) + O = I.remove(user) + if(O && istype(O)) + + // Stop the organ from continuing to reject. + O.organ_data.rejecting = null + + // Transfer over some blood data, if the organ doesn't have data. + var/datum/reagent/blood/organ_blood = O.reagents.reagent_list["blood"] + if(!organ_blood || !organ_blood.data["blood_DNA"]) + target.vessel.trans_to(O, 5, 1, 1) + + // Kinda redundant, but I'm getting some buggy behavior. + target.internal_organs_by_name[target.op_stage.current_organ] = null + target.internal_organs_by_name -= target.op_stage.current_organ + target.internal_organs -= O.organ_data + affected.internal_organs -= O.organ_data + O.removed(target,user) + + target.op_stage.current_organ = null + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(BRUISE, 20) + +/datum/surgery_step/internal/replace_organ + allowed_tools = list( + /obj/item/organ = 100 + ) + + min_duration = 60 + max_duration = 80 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + var/obj/item/organ/O = tool + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/organ_compatible + var/organ_missing + + if(!istype(O)) + return 0 + + if(target.species && target.species.has_organ[O.organ_tag]) + + if(!O.health) + user << "\red \The [O.organ_tag] is dead." + return 0 + + if(!target.internal_organs_by_name[O.organ_tag]) + organ_missing = 1 + else + user << "\red \The [target] already has a [O.organ_tag]." //TODO: grammar. + return 0 + + if(O.organ_data && affected.name == O.organ_data.parent_organ) + organ_compatible = 1 + else + user << "\red \The [O.organ_tag] doesn't normally go in \the [affected.display_name]." + return 0 + else + user << "\red \A [target.species.name] doesn't normally have a [O.organ_tag]." //TODO: grammar. + return 0 + + return ..() && organ_missing && organ_compatible + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] starts transplanting \the [tool] into [target]'s [affected.display_name].", \ + "You start transplanting \the [tool] into [target]'s [affected.display_name].") + target.custom_pain("Someone's rooting around in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\blue [user] has transplanted \the [tool] into [target]'s [affected.display_name].", \ + "\blue You have transplanted \the [tool] into [target]'s [affected.display_name].") + user.drop_item(tool) + var/obj/item/organ/O = tool + + if(istype(O)) + + if(!O.organ_data.transplant_data) + O.organ_data.transplant_data = list() + O.organ_data.transplant_data["species"] = target.species.name + O.organ_data.transplant_data["blood_type"] = target.dna.b_type + O.organ_data.transplant_data["blood_DNA"] = target.dna.unique_enzymes + + O.organ_data.owner = target + target.internal_organs |= O.organ_data + affected.internal_organs |= O.organ_data + target.internal_organs_by_name[O.organ_tag] = O.organ_data + O.organ_data.status |= ORGAN_CUT_AWAY + O.replaced(target) + + del(O) + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, damaging \the [tool]!", \ + "\red Your hand slips, damaging \the [tool]!") + var/obj/item/organ/I = tool + if(istype(I)) + I.organ_data.take_damage(rand(3,5),0) + +/datum/surgery_step/internal/attach_organ + allowed_tools = list( + /obj/item/weapon/FixOVein = 100, \ + /obj/item/stack/cable_coil = 75 + ) + + min_duration = 100 + max_duration = 120 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!..()) + return 0 + + target.op_stage.current_organ = null + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/datum/organ/internal/I = target.internal_organs_by_name[organ] + if(I.status & ORGAN_CUT_AWAY && I.parent_organ == target_zone) + removable_organs |= organ + + var/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in removable_organs + if(!organ_to_replace) + return 0 + + target.op_stage.current_organ = organ_to_replace + return ..() + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] begins reattaching [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start reattaching [target]'s [target.op_stage.current_organ] with \the [tool].") + target.custom_pain("Someone's digging needles into your [target.op_stage.current_organ]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] has reattached [target]'s [target.op_stage.current_organ] with \the [tool]." , \ + "\blue You have reattached [target]'s [target.op_stage.current_organ] with \the [tool].") + + var/datum/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] + if(I && istype(I)) + I.status &= ~ORGAN_CUT_AWAY + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(BRUISE, 20) + +////////////////////////////////////////////////////////////////// +// HEART SURGERY // +////////////////////////////////////////////////////////////////// +// To be finished after some tests. +// /datum/surgery_step/ribcage/heart/cut +// allowed_tools = list( +// /obj/item/weapon/scalpel = 100, \ +// /obj/item/weapon/kitchenknife = 75, \ +// /obj/item/weapon/shard = 50, \ +// ) + +// min_duration = 30 +// max_duration = 40 + +// can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) +// return ..() && target.op_stage.ribcage == 2 \ No newline at end of file diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 67f3cb82dec..ccd9d388e26 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -27,7 +27,7 @@ internal_bleeding = 1 break - return affected.open == 2 && internal_bleeding + return affected.open >= 2 && internal_bleeding begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -59,7 +59,7 @@ /obj/item/weapon/kitchenknife = 75, \ /obj/item/weapon/shard = 50, \ ) - + can_infect = 1 blood_level = 1 @@ -72,10 +72,10 @@ if (target_zone == "mouth" || target_zone == "eyes") return 0 - + var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && (affected.status & ORGAN_DEAD) + return affected.open >= 2 && (affected.status & ORGAN_DEAD) begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -105,7 +105,7 @@ /obj/item/weapon/reagent_containers/spray = 50, /obj/item/weapon/reagent_containers/glass/bucket = 50, ) - + can_infect = 0 blood_level = 0 @@ -115,7 +115,7 @@ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if (!istype(tool, /obj/item/weapon/reagent_containers)) return 0 - + var/obj/item/weapon/reagent_containers/container = tool if(!container.reagents.has_reagent("peridaxon")) return 0 @@ -125,7 +125,7 @@ if (target_zone == "mouth" || target_zone == "eyes") return 0 - + var/datum/organ/external/affected = target.get_organ(target_zone) return affected.open == 3 && (affected.status & ORGAN_DEAD) @@ -138,34 +138,34 @@ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) - + if (!istype(tool, /obj/item/weapon/reagent_containers)) return - + var/obj/item/weapon/reagent_containers/container = tool - + var/trans = container.reagents.trans_to(target, container.amount_per_transfer_from_this) if (trans > 0) container.reagents.reaction(target, INGEST) //technically it's contact, but the reagents are being applied to internal tissue - + if(container.reagents.has_reagent("peridaxon")) affected.status &= ~ORGAN_DEAD - + user.visible_message("\blue [user] applies [trans] units of the solution to affected tissue in [target]'s [affected.display_name]", \ "\blue You apply [trans] units of the solution to affected tissue in [target]'s [affected.display_name] with \the [tool].") fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) - + if (!istype(tool, /obj/item/weapon/reagent_containers)) return - + var/obj/item/weapon/reagent_containers/container = tool - + var/trans = container.reagents.trans_to(target, container.amount_per_transfer_from_this) container.reagents.reaction(target, INGEST) //technically it's contact, but the reagents are being applied to internal tissue - + user.visible_message("\red [user]'s hand slips, applying [trans] units of the solution to the wrong place in [target]'s [affected.display_name] with the [tool]!" , \ "\red Your hand slips, applying [trans] units of the solution to the wrong place in [target]'s [affected.display_name] with the [tool]!") - + //no damage or anything, just wastes medicine diff --git a/code/modules/surgery/ribcage.dm b/code/modules/surgery/ribcage.dm deleted file mode 100644 index c14d065cd9b..00000000000 --- a/code/modules/surgery/ribcage.dm +++ /dev/null @@ -1,335 +0,0 @@ -//Procedures in this file: Generic ribcage opening steps, Removing alien embryo, Fixing internal organs. -////////////////////////////////////////////////////////////////// -// GENERIC RIBCAGE SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery_step/ribcage - priority = 2 - can_infect = 1 - blood_level = 1 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return target_zone == "chest" - -/datum/surgery_step/ribcage/saw_ribcage - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (!hasorgans(target)) - return - var/datum/organ/external/affected = target.get_organ(target_zone) - return ..() && target.op_stage.ribcage == 0 && affected.open >= 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] begins to cut through [target]'s ribcage with \the [tool].", \ - "You begin to cut through [target]'s ribcage with \the [tool].") - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has cut [target]'s ribcage open with \the [tool].", \ - "\blue You have cut [target]'s ribcage open with \the [tool].") - target.op_stage.ribcage = 1 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cracking [target]'s ribcage with \the [tool]!" , \ - "\red Your hand slips, cracking [target]'s ribcage with \the [tool]!" ) - var/datum/organ/external/affected = target.get_organ(target_zone) - affected.createwound(CUT, 20) - affected.fracture() - - -/datum/surgery_step/ribcage/retract_ribcage - allowed_tools = list( - /obj/item/weapon/retractor = 100, \ - /obj/item/weapon/crowbar = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - min_duration = 30 - max_duration = 40 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.ribcage == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts to force open the ribcage in [target]'s torso with \the [tool]." - var/self_msg = "You start to force open the ribcage in [target]'s torso with \the [tool]." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\blue [user] forces open [target]'s ribcage with \the [tool]." - var/self_msg = "\blue You force open [target]'s ribcage with \the [tool]." - user.visible_message(msg, self_msg) - target.op_stage.ribcage = 2 - - // Whoops! - if(prob(10)) - var/datum/organ/external/affected = target.get_organ(target_zone) - affected.fracture() - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\red [user]'s hand slips, breaking [target]'s ribcage!" - var/self_msg = "\red Your hand slips, breaking [target]'s ribcage!" - user.visible_message(msg, self_msg) - var/datum/organ/external/affected = target.get_organ(target_zone) - affected.createwound(BRUISE, 20) - affected.fracture() - -/datum/surgery_step/ribcage/close_ribcage - allowed_tools = list( - /obj/item/weapon/retractor = 100, \ - /obj/item/weapon/crowbar = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - - min_duration = 20 - max_duration = 40 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts bending [target]'s ribcage back into place with \the [tool]." - var/self_msg = "You start bending [target]'s ribcage back into place with \the [tool]." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\blue [user] bends [target]'s ribcage back into place with \the [tool]." - var/self_msg = "\blue You bend [target]'s ribcage back into place with \the [tool]." - user.visible_message(msg, self_msg) - - target.op_stage.ribcage = 1 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\red [user]'s hand slips, bending [target]'s ribs the wrong way!" - var/self_msg = "\red Your hand slips, bending [target]'s ribs the wrong way!" - user.visible_message(msg, self_msg) - var/datum/organ/external/chest/affected = target.get_organ("chest") - affected.createwound(BRUISE, 20) - affected.fracture() - if (prob(40)) - user.visible_message("\red A rib pierces the lung!") - target.rupture_lung() - -/datum/surgery_step/ribcage/mend_ribcage - allowed_tools = list( - /obj/item/weapon/bonegel = 100, \ - /obj/item/weapon/screwdriver = 75 - ) - - min_duration = 20 - max_duration = 40 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.ribcage == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts applying \the [tool] to [target]'s ribcage." - var/self_msg = "You start applying \the [tool] to [target]'s ribcage." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\blue [user] applied \the [tool] to [target]'s ribcage." - var/self_msg = "\blue You applied \the [tool] to [target]'s ribcage." - user.visible_message(msg, self_msg) - - target.op_stage.ribcage = 0 - -////////////////////////////////////////////////////////////////// -// ALIEN EMBRYO SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery_step/ribcage/remove_embryo - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - blood_level = 2 - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/embryo = 0 - for(var/obj/item/alien_embryo/A in target) - embryo = 1 - break - return ..() && embryo && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts to pull something out from [target]'s ribcage with \the [tool]." - var/self_msg = "You start to pull something out from [target]'s ribcage with \the [tool]." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user] rips the larva out of [target]'s ribcage!", - "You rip the larva out of [target]'s ribcage!") - - for(var/obj/item/alien_embryo/A in target) - A.loc = A.loc.loc - - -////////////////////////////////////////////////////////////////// -// CHEST INTERNAL ORGAN SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery_step/ribcage/fix_chest_internal - allowed_tools = list( - /obj/item/stack/medical/advanced/bruise_pack= 100, \ - /obj/item/stack/medical/bruise_pack = 20, \ - /obj/item/stack/medical/bruise_pack/tajaran = 70, \ - ) - - min_duration = 70 - max_duration = 90 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if(!hasorgans(target)) - return 0 - - var/is_chest_organ_damaged = 0 - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) - if(I.damage > 0) - is_chest_organ_damaged = 1 - break - return ..() && is_chest_organ_damaged && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/tool_name = "\the [tool]" - if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) - tool_name = "regenerative membrane" - if (istype(tool, /obj/item/stack/medical/bruise_pack)) - if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) - tool_name = "the poultice" - else - tool_name = "the bandaid" - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) - if(I && I.damage > 0) - if(I.robotic < 2) - user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ - "You start treating damage to [target]'s [I.name] with [tool_name]." ) - else - user.visible_message("[user] attempts to repair [target]'s mechanical [I.name] with [tool_name]...", \ - "\blue You attempt to repair [target]'s mechanical [I.name] with [tool_name]...") - - target.custom_pain("The pain in your chest is living hell!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/tool_name = "\the [tool]" - if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) - tool_name = "regenerative membrane" - if (istype(tool, /obj/item/stack/medical/bruise_pack)) - if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) - tool_name = "the poultice" - else - tool_name = "the bandaid" - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) - if(I && I.damage > 0) - if(I.robotic < 2) - user.visible_message("\blue [user] treats damage to [target]'s [I.name] with [tool_name].", \ - "\blue You treat damage to [target]'s [I.name] with [tool_name]." ) - else - user.visible_message("\blue [user] pokes [target]'s mechanical [I.name] with [tool_name]...", \ - "\blue You poke [target]'s mechanical [I.name] with [tool_name]... \red For no effect, since it's robotic.") - I.damage = 0 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/chest/affected = target.get_organ("chest") - user.visible_message("\red [user]'s hand slips, getting mess and tearing the inside of [target]'s chest with \the [tool]!", \ - "\red Your hand slips, getting mess and tearing the inside of [target]'s chest with \the [tool]!") - var/dam_amt = 2 - - if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) - target.adjustToxLoss(5) - - else if (istype(tool, /obj/item/stack/medical/bruise_pack)) - if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) - target.adjustToxLoss(7) - else - dam_amt = 5 - target.adjustToxLoss(10) - affected.createwound(CUT, 5) - - for(var/datum/organ/internal/I in affected.internal_organs) - if(I && I.damage > 0) - I.take_damage(dam_amt,0) - -/datum/surgery_step/ribcage/fix_chest_internal_robot //For artificial organs - allowed_tools = list( - /obj/item/stack/nanopaste = 100, \ - /obj/item/weapon/bonegel = 30, \ - /obj/item/weapon/screwdriver = 70, \ - ) - - min_duration = 70 - max_duration = 90 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if(!hasorgans(target)) - return 0 - - var/is_chest_organ_damaged = 0 - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) if(I.damage > 0) - is_chest_organ_damaged = 1 - break - return ..() && is_chest_organ_damaged && heart.robotic == 2 && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - - if(heart.damage > 0) - user.visible_message("[user] starts mending the mechanisms on [target]'s heart with \the [tool].", \ - "You start mending the mechanisms on [target]'s heart with \the [tool]." ) - target.custom_pain("The pain in your chest is living hell!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - if(heart.damage > 0) - user.visible_message("\blue [user] repairs [target]'s heart with \the [tool].", \ - "\blue You repair [target]'s heart with \the [tool]." ) - heart.damage = 0 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - user.visible_message("\red [user]'s hand slips, smearing [tool] in the incision in [target]'s heart, gumming it up!!" , \ - "\red Your hand slips, smearing [tool] in the incision in [target]'s heart, gumming it up!") - heart.take_damage(5, 0) - target.adjustToxLoss(5) - -////////////////////////////////////////////////////////////////// -// HEART SURGERY // -////////////////////////////////////////////////////////////////// -// To be finished after some tests. -// /datum/surgery_step/ribcage/heart/cut -// allowed_tools = list( -// /obj/item/weapon/scalpel = 100, \ -// /obj/item/weapon/kitchenknife = 75, \ -// /obj/item/weapon/shard = 50, \ -// ) - -// min_duration = 30 -// max_duration = 40 - -// can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) -// return ..() && target.op_stage.ribcage == 2 - diff --git a/code/modules/surgery/slimes.dm b/code/modules/surgery/slimes.dm new file mode 100644 index 00000000000..d962cfd3f4b --- /dev/null +++ b/code/modules/surgery/slimes.dm @@ -0,0 +1,93 @@ +////////////////////////////////////////////////////////////////// +// SLIME CORE EXTRACTION // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/slime + is_valid_target(mob/living/carbon/slime/target) + return istype(target, /mob/living/carbon/slime/) + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return target.stat == 2 + +/datum/surgery_step/slime/cut_flesh + allowed_tools = list( + /obj/item/weapon/scalpel = 100, \ + /obj/item/weapon/kitchenknife = 75, \ + /obj/item/weapon/shard = 50, \ + ) + + min_duration = 30 + max_duration = 50 + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return ..() && target.core_removal_stage == 0 + + begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("[user] starts cutting through [target]'s flesh with \the [tool].", \ + "You start cutting through [target]'s flesh with \the [tool].") + + end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] cuts through [target]'s flesh with \the [tool].", \ + "\blue You cut through [target]'s flesh with \the [tool], revealing its silky innards.") + target.core_removal_stage = 1 + + fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, tearing [target]'s flesh with \the [tool]!", \ + "\red Your hand slips, tearing [target]'s flesh with \the [tool]!") + +/datum/surgery_step/slime/cut_innards + allowed_tools = list( + /obj/item/weapon/scalpel = 100, \ + /obj/item/weapon/kitchenknife = 75, \ + /obj/item/weapon/shard = 50, \ + ) + + min_duration = 30 + max_duration = 50 + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return ..() && target.core_removal_stage == 1 + + begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("[user] starts cutting [target]'s silky innards apart with \the [tool].", \ + "You start cutting [target]'s silky innards apart with \the [tool].") + + end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] cuts [target]'s innards apart with \the [tool], exposing the cores.", \ + "\blue You cut [target]'s innards apart with \the [tool], exposing the cores.") + target.core_removal_stage = 2 + + fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, tearing [target]'s innards with \the [tool]!", \ + "\red Your hand slips, tearing [target]'s innards with \the [tool]!") + +/datum/surgery_step/slime/saw_core + allowed_tools = list( + /obj/item/weapon/circular_saw = 100, \ + /obj/item/weapon/hatchet = 75 + ) + + min_duration = 50 + max_duration = 70 + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return ..() && (istype(target) && target.core_removal_stage == 2 && target.cores > 0) //This is being passed a human as target, unsure why. + + begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("[user] starts cutting out one of [target]'s cores with \the [tool].", \ + "You start cutting out one of [target]'s cores with \the [tool].") + + end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + target.cores-- + user.visible_message("\blue [user] cuts out one of [target]'s cores with \the [tool].",, \ + "\blue You cut out one of [target]'s cores with \the [tool]. [target.cores] cores left.") + + if(target.cores >= 0) + new target.coretype(target.loc) + if(target.cores <= 0) + target.icon_state = "[target.colour] baby slime dead-nocore" + + + fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, causing \him to miss the core!", \ + "\red Your hand slips, causing you to miss the core!") \ No newline at end of file diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index b0116585ab6..9ce44d12607 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -86,12 +86,15 @@ proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool) //check if tool is right or close enough and if this step is possible if( S.tool_quality(tool) && S.can_use(user, M, user.zone_sel.selecting, tool) && S.is_valid_target(M)) S.begin_step(user, M, user.zone_sel.selecting, tool) //start on it - //We had proper tools! (or RNG smiled.) and User did not move or change hands. + //We had proper tools! (or RNG smiled.) and user did not move or change hands. if( prob(S.tool_quality(tool)) && do_mob(user, M, rand(S.min_duration, S.max_duration))) S.end_step(user, M, user.zone_sel.selecting, tool) //finish successfully else if (tool in user.contents && user.Adjacent(M)) //or S.fail_step(user, M, user.zone_sel.selecting, tool) //malpractice~ return 1 //don't want to do weapony things after surgery + if (user.a_intent == "help") + user << "\red You can't see any useful way to use [tool] on [M]." + return 1 return 0 proc/sort_surgeries() @@ -114,5 +117,5 @@ proc/sort_surgeries() var/eyes = 0 var/face = 0 var/appendix = 0 - var/ribcage = 0 var/head_reattach = 0 + var/current_organ diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm index 41fda7a1505..3ebeefeba8e 100644 --- a/code/modules/virus2/effect.dm +++ b/code/modules/virus2/effect.dm @@ -203,7 +203,7 @@ if(istype(mob, /mob/living/carbon/human)) var/mob/living/carbon/human/H = mob var/datum/organ/internal/brain/B = H.internal_organs_by_name["brain"] - if (B.damage < B.min_broken_damage) + if (B && B.damage < B.min_broken_damage) B.take_damage(5) else mob.setBrainLoss(50) diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index a5c7e0c7cdded57a409504f7390a1cb3adc6af7a..58a7aaf25c046d161364add6d4279166bd4ea571 100644 GIT binary patch literal 14638 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