From a3ab9ee833a053d0a9f3db38ebf9cb2d65c542c5 Mon Sep 17 00:00:00 2001 From: Helg2 <93882977+Helg2@users.noreply.github.com> Date: Fri, 9 Aug 2024 21:24:40 +0300 Subject: [PATCH] Adds a stomach organ, pills, food and etc go into stomach and only then to blood. (#69) * hmmmmmmmmm * vomitting * Update organ_internal.dm * hmm * Update condiment.dm * hmm * Update mobs.dm * Update holder.dm * Update holder.dm * Update snacks.dm * Update holder.dm * Update living_health_procs.dm * Update holder.dm * defib fixes * guh * Update limbs.dm * Update species.dm * new() * Update organs.dm * get_damage broken stuff in the future detected * Update living_health_procs.dm * med analyzer stomach chem contents * peri * Update medical.dm * Update human.dm * Update shock.dm * eh * Update organs.dm * sanity checks? * Update death.dm * Update organs.dm * vomitting out reagents * eh * ueh * mhm * delete props * Update organs.dm * Update human_defense.dm * meh * eh * vomit * Update human_status_procs.dm * eh --- .../Campaign maps/nt_base/nt_base.dmm | 2 +- .../Pillar_of_Spring/TGS_Pillar_of_Spring.dmm | 12 +- _maps/map_files/gelida_iv/gelida_iv.dmm | 2 +- code/__DEFINES/mobs.dm | 12 +- code/datums/status_effects/debuffs.dm | 4 +- .../objects/effects/decals/Cleanable/misc.dm | 1 - .../effects/spawners/random/medical.dm | 14 +- .../reagent_containers/food/condiment.dm | 2 +- .../items/reagent_containers/food/drinks.dm | 4 +- .../items/reagent_containers/food/snacks.dm | 12 +- .../objects/items/reagent_containers/pill.dm | 8 +- code/game/objects/items/scanners.dm | 20 +- .../game/objects/items/tools/kitchen_tools.dm | 2 +- code/game/objects/machinery.dm | 9 +- code/game/objects/machinery/autodoc.dm | 19 +- code/game/objects/machinery/flasher.dm | 2 - .../machinery/portable_reagent_tank.dm | 2 +- code/game/objects/structures/prop.dm | 34 -- code/game/objects/structures/supplypod.dm | 10 - .../admin/verbs/centcom_podlauncher.dm | 4 - code/modules/admin/verbs/podlauncher.dm | 5 - code/modules/mob/living/brain/MMI.dm | 139 ------ code/modules/mob/living/brain/brain_item.dm | 59 --- code/modules/mob/living/brain/death.dm | 10 - code/modules/mob/living/brain/emote.dm | 40 -- code/modules/mob/living/brain/life.dm | 21 +- code/modules/mob/living/carbon/carbon.dm | 10 +- code/modules/mob/living/carbon/human/death.dm | 5 +- code/modules/mob/living/carbon/human/human.dm | 7 +- .../mob/living/carbon/human/human_damage.dm | 3 - .../mob/living/carbon/human/human_defense.dm | 11 +- .../living/carbon/human/human_status_procs.dm | 6 +- .../living/carbon/human/life/handle_organs.dm | 2 +- .../mob/living/carbon/human/species.dm | 8 +- .../modules/mob/living/carbon/human/zombie.dm | 3 +- code/modules/mob/living/carbon/life.dm | 2 - code/modules/mob/living/carbon/shock.dm | 3 +- .../castes/carrier/abilities_carrier.dm | 5 +- .../mob/living/carbon/xenomorph/embryo.dm | 4 +- .../mob/living/carbon/xenomorph/xenomorph.dm | 3 - code/modules/mob/living/living.dm | 5 - .../modules/mob/living/living_health_procs.dm | 4 +- code/modules/organs/_organ.dm | 78 ++++ code/modules/organs/limb_objects.dm | 1 - code/modules/organs/limbs.dm | 5 +- code/modules/organs/organ_alien.dm | 76 ---- code/modules/organs/organ_internal.dm | 403 ------------------ code/modules/organs/organ_objects.dm | 225 ---------- code/modules/organs/organ_props.dm | 43 ++ code/modules/organs/organs.dm | 240 +++++++++++ code/modules/predator/yautja/chems.dm | 2 +- code/modules/reagents/holder.dm | 47 +- code/modules/reagents/reagents/drink.dm | 2 +- code/modules/reagents/reagents/medical.dm | 12 +- code/modules/surgery/organs_internal.dm | 62 +-- icons/obj/items/organs.dmi | Bin 3470 -> 7427 bytes tgmc.dme | 9 +- .../tgui/interfaces/CentcomPodLauncher.js | 9 - tgui/packages/tgui/interfaces/MedScanner.js | 31 +- tgui/packages/tgui/interfaces/PodLauncher.js | 1 - 60 files changed, 523 insertions(+), 1253 deletions(-) delete mode 100644 code/modules/mob/living/brain/MMI.dm delete mode 100644 code/modules/mob/living/brain/brain_item.dm delete mode 100644 code/modules/mob/living/brain/emote.dm create mode 100644 code/modules/organs/_organ.dm delete mode 100644 code/modules/organs/organ_alien.dm delete mode 100644 code/modules/organs/organ_internal.dm delete mode 100644 code/modules/organs/organ_objects.dm create mode 100644 code/modules/organs/organ_props.dm create mode 100644 code/modules/organs/organs.dm diff --git a/_maps/map_files/Campaign maps/nt_base/nt_base.dmm b/_maps/map_files/Campaign maps/nt_base/nt_base.dmm index 381db7ed5c3..977e31aa3a0 100644 --- a/_maps/map_files/Campaign maps/nt_base/nt_base.dmm +++ b/_maps/map_files/Campaign maps/nt_base/nt_base.dmm @@ -21394,7 +21394,7 @@ pixel_x = -11 }, /obj/effect/decal/cleanable/blood/gibs/body, -/obj/item/prop/organ/heart, +/obj/item/organ/heart, /turf/open/floor/tile/dark2{ dir = 8 }, diff --git a/_maps/map_files/Pillar_of_Spring/TGS_Pillar_of_Spring.dmm b/_maps/map_files/Pillar_of_Spring/TGS_Pillar_of_Spring.dmm index f5dc9eb1b96..9ed559c6663 100644 --- a/_maps/map_files/Pillar_of_Spring/TGS_Pillar_of_Spring.dmm +++ b/_maps/map_files/Pillar_of_Spring/TGS_Pillar_of_Spring.dmm @@ -8543,7 +8543,7 @@ /area/mainship/command/self_destruct) "lcA" = ( /obj/machinery/optable, -/obj/item/prop/organ/kidneys, +/obj/item/organ/kidneys, /turf/open/floor/cult, /area/medical/morgue) "lcL" = ( @@ -9573,11 +9573,11 @@ "mcR" = ( /obj/structure/toilet, /obj/structure/closet/crate/freezer, -/obj/item/prop/organ/kidneys, -/obj/item/prop/organ/kidneys, -/obj/item/prop/organ/kidneys, -/obj/item/prop/organ/kidneys, -/obj/item/prop/organ/kidneys, +/obj/item/organ/kidneys, +/obj/item/organ/kidneys, +/obj/item/organ/kidneys, +/obj/item/organ/kidneys, +/obj/item/organ/kidneys, /turf/open/floor/mainship/floor, /area/mainship/medical/upper_medical) "mdp" = ( diff --git a/_maps/map_files/gelida_iv/gelida_iv.dmm b/_maps/map_files/gelida_iv/gelida_iv.dmm index b26e8f42cbc..b33d4197be5 100644 --- a/_maps/map_files/gelida_iv/gelida_iv.dmm +++ b/_maps/map_files/gelida_iv/gelida_iv.dmm @@ -23274,7 +23274,7 @@ pixel_x = -11 }, /obj/effect/decal/cleanable/blood/gibs/body, -/obj/item/prop/organ/heart, +/obj/item/organ/heart, /turf/open/floor/tile/dark2{ dir = 8 }, diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index ad05dcc8767..fdcd3aa0f27 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -210,17 +210,6 @@ GLOBAL_LIST_INIT(xenoupgradetiers, list(XENO_UPGRADE_BASETYPE, XENO_UPGRADE_INVA ///////////////////INTERNAL ORGANS DEFINES/////////////////// -#define ORGAN_ASSISTED 1 -#define ORGAN_ROBOT 2 - -#define ORGAN_HEART 1 -#define ORGAN_LUNGS 2 -#define ORGAN_LIVER 3 -#define ORGAN_KIDNEYS 4 -#define ORGAN_BRAIN 5 -#define ORGAN_EYES 6 -#define ORGAN_APPENDIX 7 - //organ slots #define ORGAN_SLOT_APPENDIX "appendix" #define ORGAN_SLOT_BRAIN "brain" @@ -228,6 +217,7 @@ GLOBAL_LIST_INIT(xenoupgradetiers, list(XENO_UPGRADE_BASETYPE, XENO_UPGRADE_INVA #define ORGAN_SLOT_EYES "eyes" #define ORGAN_SLOT_HEART "heart" #define ORGAN_SLOT_LIVER "liver" +#define ORGAN_SLOT_STOMACH "stomach" #define ORGAN_SLOT_LUNGS "lungs" #define ORGAN_SLOT_KIDNEYS "kidneys" diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 67fc9d7b579..a629aa5fd42 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -494,8 +494,8 @@ living_owner.adjustToxLoss(3) if(prob(15)) living_owner.adjust_Losebreath(5) - if(prob(15)) - living_owner.vomit() + if(carbon_owner && prob(15)) + carbon_owner.vomit() if(carbon_owner && prob(15)) var/datum/internal_organ/organ = pick(carbon_owner.internal_organs) if(organ) diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index cd77a7c725e..71f65595d8f 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -112,7 +112,6 @@ icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") - /obj/effect/decal/cleanable/tomato_smudge name = "tomato smudge" desc = "It's red." diff --git a/code/game/objects/effects/spawners/random/medical.dm b/code/game/objects/effects/spawners/random/medical.dm index 1b3d2e978df..558d762a05d 100644 --- a/code/game/objects/effects/spawners/random/medical.dm +++ b/code/game/objects/effects/spawners/random/medical.dm @@ -100,13 +100,13 @@ name = "Random surgical organ spawner" icon_state = "random_organ" loot = list( - /obj/item/prop/organ/brain, - /obj/item/prop/organ/heart, - /obj/item/prop/organ/lungs, - /obj/item/prop/organ/kidneys, - /obj/item/prop/organ/eyes, - /obj/item/prop/organ/liver, - /obj/item/prop/organ/appendix, + /obj/item/organ/brain, + /obj/item/organ/heart, + /obj/item/organ/lungs, + /obj/item/organ/kidneys, + /obj/item/organ/eyes, + /obj/item/organ/liver, + /obj/item/organ/appendix, ) /obj/effect/spawner/random/medical/medbottle diff --git a/code/game/objects/items/reagent_containers/food/condiment.dm b/code/game/objects/items/reagent_containers/food/condiment.dm index 2d39a4e761f..b849b04284f 100644 --- a/code/game/objects/items/reagent_containers/food/condiment.dm +++ b/code/game/objects/items/reagent_containers/food/condiment.dm @@ -50,7 +50,7 @@ if(reagents.total_volume) record_reagent_consumption(min(10, reagents.total_volume), reagents.reagent_list, user, M) reagents.reaction(M, INGEST) - reagents.trans_to(M, 10) + reagents.trans_to(M, 10, transfer_to_stomach = TRUE) playsound(M.loc,'sound/items/drink.ogg', 15, 1) return 1 return 0 diff --git a/code/game/objects/items/reagent_containers/food/drinks.dm b/code/game/objects/items/reagent_containers/food/drinks.dm index 8c9965b70f5..7cc4de2153d 100644 --- a/code/game/objects/items/reagent_containers/food/drinks.dm +++ b/code/game/objects/items/reagent_containers/food/drinks.dm @@ -36,7 +36,7 @@ record_reagent_consumption(min(gulp_size, reagents.total_volume), reagents.reagent_list, user) if(reagents.total_volume) reagents.reaction(M, INGEST) - reagents.trans_to(M, gulp_size) + reagents.trans_to(M, gulp_size, transfer_to_stomach = TRUE) playsound(M.loc,'sound/items/drink.ogg', 15, 1) return TRUE else @@ -56,7 +56,7 @@ if(reagents.total_volume) reagents.reaction(M, INGEST) - reagents.trans_to(M, gulp_size) + reagents.trans_to(M, gulp_size, transfer_to_stomach = TRUE) playsound(M.loc,'sound/items/drink.ogg', 15, 1) return TRUE diff --git a/code/game/objects/items/reagent_containers/food/snacks.dm b/code/game/objects/items/reagent_containers/food/snacks.dm index 6a10c4e6c41..cc961f883d5 100644 --- a/code/game/objects/items/reagent_containers/food/snacks.dm +++ b/code/game/objects/items/reagent_containers/food/snacks.dm @@ -113,10 +113,10 @@ */ //Why is bitesize used instead of an actual portion??? record_reagent_consumption(bitesize, reagents.reagent_list, user, M) - reagents.trans_to(M, bitesize) + reagents.trans_to(M, bitesize, transfer_to_stomach = TRUE) else record_reagent_consumption(reagents.total_volume, reagents.reagent_list, user, M) - reagents.trans_to(M, reagents.total_volume) + reagents.trans_to(M, reagents.total_volume, transfer_to_stomach = TRUE) bitecount++ On_Consume(M) return TRUE @@ -858,12 +858,12 @@ var/mob/living/carbon/human/H = M var/datum/limb/E = H.get_limb("chest") E.fracture() - for (var/datum/internal_organ/I in E.internal_organs) + for(var/datum/internal_organ/I in E.internal_organs) I.take_damage(rand(I.min_bruised_damage, I.min_broken_damage+1)) - if (!E.hidden && prob(60)) //set it snuggly + if(!E.hidden && prob(60)) //set it snuggly E.hidden = surprise E.cavity = 0 - else //someone is having a bad day + else //someone is having a bad day E.createwound(CUT, 30) surprise.embed_into(M, E) qdel(src) @@ -1555,7 +1555,7 @@ /obj/item/reagent_containers/food/snacks/lollipop/proc/handle_reagents() var/fraction = min(FOOD_METABOLISM/reagents.total_volume, 1) reagents.reaction(owner, INGEST, fraction) - if(!reagents.trans_to(owner, FOOD_METABOLISM)) + if(!reagents.trans_to(owner, FOOD_METABOLISM, transfer_to_stomach = TRUE)) reagents.remove_any(FOOD_METABOLISM) /obj/item/reagent_containers/food/snacks/lollipop/process() diff --git a/code/game/objects/items/reagent_containers/pill.dm b/code/game/objects/items/reagent_containers/pill.dm index 50914a43f65..3d68c9fadb1 100644 --- a/code/game/objects/items/reagent_containers/pill.dm +++ b/code/game/objects/items/reagent_containers/pill.dm @@ -1,7 +1,3 @@ -//////////////////////////////////////////////////////////////////////////////// -/// Pills. -//////////////////////////////////////////////////////////////////////////////// - /obj/item/reagent_containers/pill name = "pill" icon = 'icons/obj/items/chemistry.dmi' @@ -39,7 +35,7 @@ if(reagents.total_volume) record_reagent_consumption(reagents.total_volume, reagents.reagent_list, user) reagents.reaction(M, INGEST) - reagents.trans_to(M, reagents.total_volume) + reagents.trans_to(M, reagents.total_volume, transfer_to_stomach = TRUE) qdel(src) return TRUE @@ -68,7 +64,7 @@ if(reagents.total_volume) record_reagent_consumption(reagents.total_volume, reagents.reagent_list, user, M) reagents.reaction(M, INGEST) - reagents.trans_to(M, reagents.total_volume) + reagents.trans_to(M, reagents.total_volume, transfer_to_stomach = TRUE) qdel(src) else qdel(src) diff --git a/code/game/objects/items/scanners.dm b/code/game/objects/items/scanners.dm index 8e9fd72dfdf..ecc8ea0cc9c 100644 --- a/code/game/objects/items/scanners.dm +++ b/code/game/objects/items/scanners.dm @@ -82,7 +82,7 @@ REAGENT SCANNER ///Skill required to have the scanner auto refresh var/upper_skill_threshold = SKILL_MEDICAL_NOVICE ///Current mob being tracked by the scanner - var/mob/living/carbon/patient + var/mob/living/carbon/human/patient ///Current user of the scanner var/mob/living/carbon/current_user ///Distance the current_user can be away from the patient and still get health data. @@ -192,6 +192,24 @@ REAGENT SCANNER ) data["has_chemicals"] = length(patient.reagents.reagent_list) data["chemicals_lists"] = chemicals_lists + + var/datum/internal_organ/stomach/belly = patient.get_organ_slot(ORGAN_SLOT_STOMACH) // should it be this way? + data["has_stomach_chemicals"] = length(belly.reagents.reagent_list) + var/list/stomach_chemicals_lists = list() + for(var/datum/reagent/reagent AS in belly.reagents.reagent_list) + if(!reagent.scannable) + data["has_unknown_chemicals"] = TRUE + continue + var/reagent_overdosed = FALSE + if(reagent.overdose_threshold && reagent.volume > reagent.overdose_threshold) + reagent_overdosed = TRUE + stomach_chemicals_lists["[reagent.name]"] = list( + "name" = reagent.name, + "amount" = round(reagent.volume, 0.1), + "od" = reagent_overdosed + ) + data["stomach_chemicals_lists"] = stomach_chemicals_lists + data["species"] = patient.species.species_flags & ROBOTIC_LIMBS ? "robot" : "human" var/list/limb_data_lists = list() diff --git a/code/game/objects/items/tools/kitchen_tools.dm b/code/game/objects/items/tools/kitchen_tools.dm index 9103ee1baff..edd3bc06f0b 100644 --- a/code/game/objects/items/tools/kitchen_tools.dm +++ b/code/game/objects/items/tools/kitchen_tools.dm @@ -35,7 +35,7 @@ if (reagents.total_volume > 0) reagents.reaction(M, INGEST) - reagents.trans_to(M, reagents.total_volume) + reagents.trans_to(M, reagents.total_volume, transfer_to_stomach = TRUE) if(M == user) visible_message(span_notice("[user] eats some [loaded] from \the [src].")) M.reagents.add_reagent(/datum/reagent/consumable/nutriment, 1) diff --git a/code/game/objects/machinery.dm b/code/game/objects/machinery.dm index f7707b32d67..7ac7a34ca48 100644 --- a/code/game/objects/machinery.dm +++ b/code/game/objects/machinery.dm @@ -413,15 +413,8 @@ dat += "" for(var/datum/internal_organ/i in occ["internal_organs"]) - - var/mech = "" - if(i.robotic == ORGAN_ASSISTED) - mech = "Assisted:
" - if(i.robotic == ORGAN_ROBOT) - mech = "Mechanical:
" - dat += "" - dat += "[i.name]N/A[i.damage]None:[mech]" + dat += "[i.name]N/A[i.damage]" dat += "" dat += "" diff --git a/code/game/objects/machinery/autodoc.dm b/code/game/objects/machinery/autodoc.dm index 950860a9e07..7af99699b89 100644 --- a/code/game/objects/machinery/autodoc.dm +++ b/code/game/objects/machinery/autodoc.dm @@ -237,11 +237,8 @@ var/organdamagesurgery = 0 for(var/datum/internal_organ/I in L.internal_organs) - if(I.robotic == ORGAN_ASSISTED||I.robotic == ORGAN_ROBOT) - // we can't deal with these - continue if(I.damage > 0) - if(I.organ_id == ORGAN_EYES) // treat eye surgery differently + if(I.slot == ORGAN_SLOT_EYES) // treat eye surgery differently continue if(organdamagesurgery > 0) continue // avoid duplicates @@ -372,7 +369,7 @@ else occupant.reagents.add_reagent(/datum/reagent/medicine/spaceacillin,inject_per_second) amount -= inject_per_second - sleep(10*surgery_mod) + sleep(10 * surgery_mod) if(ADSURGERY_DAMAGE) say("Beginning organ restoration.") @@ -386,15 +383,15 @@ if(S.limb_ref.body_part != GROIN) open_encased(occupant, S.limb_ref) - if(!istype(S.organ_ref,/datum/internal_organ/brain)) + if(!istype(S.organ_ref, /datum/internal_organ/brain)) sleep(FIX_ORGAN_MAX_DURATION*surgery_mod) else if(S.organ_ref.damage > BONECHIPS_MAX_DAMAGE) - sleep(HEMOTOMA_MAX_DURATION*surgery_mod) - sleep(BONECHIPS_REMOVAL_MAX_DURATION*surgery_mod) + sleep(HEMOTOMA_MAX_DURATION * surgery_mod) + sleep(BONECHIPS_REMOVAL_MAX_DURATION * surgery_mod) if(!surgery) break - if(istype(S.organ_ref,/datum/internal_organ)) + if(istype(S.organ_ref, /datum/internal_organ)) S.organ_ref.heal_organ_damage(S.organ_ref.damage) else say("Organ is missing.") @@ -411,7 +408,7 @@ say("Procedure has been deemed unnecessary.") surgery_todo_list -= S continue - if(istype(S.organ_ref,/datum/internal_organ/eyes)) + if(istype(S.organ_ref, /datum/internal_organ/eyes)) var/datum/internal_organ/eyes/E = S.organ_ref if(E.eye_surgery_stage == 0) @@ -1219,8 +1216,6 @@ var/datum/limb/L = i for(var/x in L.internal_organs) var/datum/internal_organ/I = x - if(I.robotic == ORGAN_ASSISTED || I.robotic == ORGAN_ROBOT) - continue if(I.damage > 0) N.fields["autodoc_manual"] += create_autodoc_surgery(L,ORGAN_SURGERY,ADSURGERY_DAMAGE,0,I) needed++ diff --git a/code/game/objects/machinery/flasher.dm b/code/game/objects/machinery/flasher.dm index eda7d506ce2..19e1e98cd50 100644 --- a/code/game/objects/machinery/flasher.dm +++ b/code/game/objects/machinery/flasher.dm @@ -83,10 +83,8 @@ else L.flash_act() - L.Paralyze(strength) - /obj/machinery/flasher/emp_act(severity) if(machine_stat & (BROKEN|NOPOWER)) ..(severity) diff --git a/code/game/objects/machinery/portable_reagent_tank.dm b/code/game/objects/machinery/portable_reagent_tank.dm index 34a417e7dc7..2d3eb64a1e3 100644 --- a/code/game/objects/machinery/portable_reagent_tank.dm +++ b/code/game/objects/machinery/portable_reagent_tank.dm @@ -87,7 +87,7 @@ record_sippies(5, reagents.reagent_list, user) playsound(user.loc,'sound/items/drink.ogg', 25, 2) reagents.reaction(user, INGEST) - reagents.trans_to(user, 5) + reagents.trans_to(user, 5, transfer_to_stomach = TRUE) return TRUE balloon_alert(user, "It's empty!") diff --git a/code/game/objects/structures/prop.dm b/code/game/objects/structures/prop.dm index b22640e2060..c1c13824c6d 100644 --- a/code/game/objects/structures/prop.dm +++ b/code/game/objects/structures/prop.dm @@ -933,40 +933,6 @@ icon = 'icons/Marine/mainship_props.dmi' icon_state = "hangarbox" -/obj/item/prop/organ - name = "organ" - desc = "It looks like it probably just plopped out. It's too decayed to be reinserted in a patient." - icon = 'icons/obj/items/organs.dmi' - icon_state = "heart" - -/obj/item/prop/organ/heart - name = "heart" - icon_state = "heart-off" - -/obj/item/prop/organ/brain - name = "brain" - icon_state = "brain1" - -/obj/item/prop/organ/appendix - name = "appendix" - icon_state = "appendix" - -/obj/item/prop/organ/lungs - name = "lungs" - icon_state = "lungs" - -/obj/item/prop/organ/kidneys - name = "kidneys" - icon_state = "kidneys" - -/obj/item/prop/organ/eyes - name = "eyes" - icon_state = "eyes" - -/obj/item/prop/organ/liver - name = "liver" - icon_state = "liver" - /obj/item/prop/aimodule name = "AI module" desc = "An AI Module for programming laws to an AI." diff --git a/code/game/objects/structures/supplypod.dm b/code/game/objects/structures/supplypod.dm index ecd56aa50f7..5e6c907ea5e 100644 --- a/code/game/objects/structures/supplypod.dm +++ b/code/game/objects/structures/supplypod.dm @@ -37,7 +37,6 @@ GLOBAL_LIST_INIT(pod_styles, list(\ var/damage = 0 var/effectStun = FALSE var/effectLimb = FALSE - var/effectOrgans = FALSE var/effectGib = FALSE var/effectStealth = FALSE var/effectQuiet = FALSE @@ -123,15 +122,6 @@ GLOBAL_LIST_INIT(pod_styles, list(\ continue E.droplimb() - if(effectOrgans && ishuman(L)) - var/mob/living/carbon/human/H = L - for(var/datum/internal_organ/IO in H.internal_organs) - var/destination = get_edge_target_turf(T, pick(GLOB.alldirs)) - var/obj/item/organ/O = IO.remove(H) - O.forceMove(T) - O.throw_at(destination, 2, 3) - sleep(0.1 SECONDS) - if(effectGib) L.adjustBruteLoss(5000) L.gib() diff --git a/code/modules/admin/verbs/centcom_podlauncher.dm b/code/modules/admin/verbs/centcom_podlauncher.dm index 6af9f59582d..33d44a8ee2b 100644 --- a/code/modules/admin/verbs/centcom_podlauncher.dm +++ b/code/modules/admin/verbs/centcom_podlauncher.dm @@ -77,7 +77,6 @@ data["styleChoice"] = temp_pod.style //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod. data["effectStun"] = temp_pod.effectStun //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish! data["effectLimb"] = temp_pod.effectLimb //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands - data["effectOrgans"] = temp_pod.effectOrgans //If true, yeets the organs out of any bodies caught under the pod when it lands data["effectBluespace"] = temp_pod.bluespace //If true, the pod deletes (in a shower of sparks) after landing data["effectStealth"] = temp_pod.effectStealth //If true, a target icon isnt displayed on the turf where the pod will land data["effectQuiet"] = temp_pod.effectQuiet //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc) @@ -241,9 +240,6 @@ if("effectLimb") //Toggle: Anyone carbon mob under the pod loses a limb when it lands temp_pod.effectLimb = !temp_pod.effectLimb . = TRUE - if("effectOrgans") //Toggle: Anyone carbon mob under the pod loses a limb when it lands - temp_pod.effectOrgans = !temp_pod.effectOrgans - . = TRUE if("effectBluespace") //Toggle: Deletes the pod after landing temp_pod.bluespace = !temp_pod.bluespace . = TRUE diff --git a/code/modules/admin/verbs/podlauncher.dm b/code/modules/admin/verbs/podlauncher.dm index 42e1495fb52..a84c7718e59 100644 --- a/code/modules/admin/verbs/podlauncher.dm +++ b/code/modules/admin/verbs/podlauncher.dm @@ -97,7 +97,6 @@ data["styleChoice"] = temp_pod.style data["effectStun"] = temp_pod.effectStun data["effectLimb"] = temp_pod.effectLimb - data["effectOrgans"] = temp_pod.effectOrgans data["effectBluespace"] = temp_pod.bluespace data["effectStealth"] = temp_pod.effectStealth data["effectQuiet"] = temp_pod.effectQuiet @@ -271,10 +270,6 @@ temp_pod.effectLimb = !temp_pod.effectLimb . = TRUE - if("effectOrgans") - temp_pod.effectOrgans = !temp_pod.effectOrgans - . = TRUE - if("effectBluespace") temp_pod.bluespace = !temp_pod.bluespace . = TRUE diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm deleted file mode 100644 index 104ebd23b61..00000000000 --- a/code/modules/mob/living/brain/MMI.dm +++ /dev/null @@ -1,139 +0,0 @@ -/// this code sucks dont use it -/obj/item/mmi - name = "Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity." - icon = 'icons/obj/items/assemblies.dmi' - icon_state = "mmi_empty" - w_class = WEIGHT_CLASS_NORMAL - - //these vars are so the mecha fabricator doesn't shit itself anymore. --NEO - - req_access = list(ACCESS_MARINE_RESEARCH) - - //Revised. Brainmob is now contained directly within object of transfer. MMI in this case. - - var/locked = 0 - var/mob/living/brain/brainmob = null//The current occupant. - - -/obj/item/mmi/attackby(obj/item/O, mob/user) - if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO - - var/obj/item/organ/brain/B = O - if(B.obj_integrity <= 0) - to_chat(user, span_warning("That brain is well and truly dead.")) - return - else if(!B.brainmob) - to_chat(user, span_warning("You aren't sure where this brain came from, but you're pretty sure it's a useless brain.")) - return - - visible_message(span_notice("[user] sticks \a [O] into \the [src].")) - - brainmob = O:brainmob - O:brainmob = null - brainmob.loc = src - brainmob.container = src - brainmob.set_stat(CONSCIOUS) - GLOB.dead_mob_list -= brainmob//Update dem lists - GLOB.alive_living_list += brainmob - - user.drop_held_item() - qdel(O) - - name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" - - locked = 1 - - return - - if(istype(O,/obj/item/card/id) && brainmob) - if(allowed(user)) - locked = !locked - to_chat(user, span_notice("You [locked ? "lock" : "unlock"] the brain holder.")) - else - to_chat(user, span_warning("Access denied.")) - return - if(brainmob) - O.attack(brainmob, user)//Oh noooeeeee - return - ..() - - //TODO: ORGAN REMOVAL UPDATE. Make the brain remain in the MMI so it doesn't lose organ data. -/obj/item/mmi/attack_self(mob/user as mob) - if(!brainmob) - to_chat(user, span_warning("You upend the MMI, but there's nothing in it.")) - else if(locked) - to_chat(user, span_warning("You upend the MMI, but the brain is clamped into place.")) - else - to_chat(user, span_notice("You upend the MMI, spilling the brain onto the floor.")) - var/obj/item/organ/brain/brain = new(user.loc) - brainmob.container = null//Reset brainmob mmi var. - brainmob.loc = brain//Throw mob into brain. - GLOB.alive_living_list -= brainmob//Get outta here - brain.brainmob = brainmob//Set the brain to use the brainmob - brainmob = null//Set mmi brainmob var to null - - icon_state = "mmi_empty" - name = "Man-Machine Interface" - -/obj/item/mmi/proc/transfer_identity(mob/living/carbon/human/H)//Same deal as the regular brain proc. Used for human-->robot people. - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.container = src - - name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" - locked = 1 - return - -/obj/item/mmi/radio_enabled - name = "Radio-enabled Man-Machine Interface" - desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity. This one comes with a built-in radio." - - var/obj/item/radio/radio = null//Let's give it a radio. - -/obj/item/mmi/radio_enabled/Initialize(mapload) - . = ..() - radio = new(src)//Spawns a radio inside the MMI. - radio.broadcasting = 1//So it's broadcasting from the start. - -/obj/item/mmi/radio_enabled/verb/Toggle_Broadcasting() - set name = "Toggle Broadcasting" - set desc = "Toggle broadcasting channel on or off." - set category = "MMI" - set src = usr.loc//In user location, or in MMI in this case. - set popup_menu = 0//Will not appear when right clicking. - - if(brainmob.stat)//Only the brainmob will trigger these so no further check is necessary. - to_chat(brainmob, "Can't do that while incapacitated or dead.") - - radio.broadcasting = radio.broadcasting==1 ? 0 : 1 - to_chat(brainmob, span_notice("Radio is [radio.broadcasting==1 ? "now" : "no longer"] broadcasting.")) - -/obj/item/mmi/radio_enabled/verb/Toggle_Listening() - set name = "Toggle Listening" - set desc = "Toggle listening channel on or off." - set category = "MMI" - set src = usr.loc - set popup_menu = 0 - - if(brainmob.stat) - to_chat(brainmob, "Can't do that while incapacitated or dead.") - - radio.listening = radio.listening==1 ? 0 : 1 - to_chat(brainmob, span_notice("Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast.")) - -/obj/item/mmi/emp_act(severity) - if(!brainmob) - return - else - switch(severity) - if(1) - brainmob.emp_damage += rand(20,30) - if(2) - brainmob.emp_damage += rand(10,20) - if(3) - brainmob.emp_damage += rand(0,10) - ..() diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm deleted file mode 100644 index c319fba32d7..00000000000 --- a/code/modules/mob/living/brain/brain_item.dm +++ /dev/null @@ -1,59 +0,0 @@ -/obj/item/organ/brain - name = "brain" - max_integrity = 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_atom = NONE - force = 1 - w_class = WEIGHT_CLASS_SMALL - throwforce = 1 - throw_speed = 3 - throw_range = 5 - attack_verb = list("attacked", "slapped", "whacked") - organ_type = /datum/internal_organ/brain - organ_tag = ORGAN_SLOT_BRAIN - - var/mob/living/brain/brainmob = null - -/obj/item/organ/brain/xeno - name = "thinkpan" - desc = "It looks kind of like an enormous wad of purple bubblegum." - icon = 'icons/mob/alien.dmi' - icon_state = "chitin" - - -/obj/item/organ/brain/proc/transfer_identity(mob/living/carbon/H) - name = "[H]'s brain" - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.timeofhostdeath = H.timeofdeath - if(H.mind) - H.mind.transfer_to(brainmob) - - to_chat(brainmob, span_notice("You feel slightly disoriented. That's normal when you're just a brain.")) - -/obj/item/organ/brain/examine(mob/user) - . = ..() - if(brainmob?.client)//if thar be a brain inside... the brain. - . += "You can feel the small spark of life still left in this one." - else - . += "This one seems particularly lifeless. Perhaps it will regain some of its luster later.." - -/obj/item/organ/brain/removed(mob/living/target,mob/living/user) - ..() - var/mob/living/carbon/human/H = target - var/obj/item/organ/brain/B = src - if(istype(B) && istype(H)) - B.transfer_identity(target) - -/obj/item/organ/brain/replaced(mob/living/target) - - if(target.key) - target.ghostize() - - if(brainmob) - if(brainmob.mind) - brainmob.mind.transfer_to(target) - else - target.key = brainmob.key diff --git a/code/modules/mob/living/brain/death.dm b/code/modules/mob/living/brain/death.dm index 71bd879e5ab..5e21e54aa24 100644 --- a/code/modules/mob/living/brain/death.dm +++ b/code/modules/mob/living/brain/death.dm @@ -1,14 +1,4 @@ -/mob/living/brain/death(gibbing, deathmessage = "beeps shrilly as the MMI flatlines!", silent) - if(stat == DEAD) - return ..() - if(!gibbing && istype(container, /obj/item/mmi)) //If not gibbing but in a container. - container.icon_state = "mmi_dead" - return ..() - - /mob/living/brain/gib() - if(istype(container, /obj/item/mmi)) - qdel(container)//Gets rid of the MMI if there is one if(loc) if(istype(loc,/obj/item/organ/brain)) qdel(loc)//Gets rid of the brain item diff --git a/code/modules/mob/living/brain/emote.dm b/code/modules/mob/living/brain/emote.dm deleted file mode 100644 index a518c9db5b0..00000000000 --- a/code/modules/mob/living/brain/emote.dm +++ /dev/null @@ -1,40 +0,0 @@ -/datum/emote/brain - mob_type_allowed_typecache = list(/mob/living/brain) - mob_type_blacklist_typecache = list() - - -/datum/emote/brain/can_run_emote(mob/user, status_check = TRUE, intentional = FALSE) - . = ..() - var/mob/living/brain/B = user - if(!istype(B) || (!(B.container && istype(B.container, /obj/item/mmi)))) - return FALSE - - -/datum/emote/brain/alarm - key = "alarm" - message = "sounds an alarm." - emote_type = EMOTE_AUDIBLE - - -/datum/emote/brain/alert - key = "alert" - message = "lets out a distressed noise." - emote_type = EMOTE_AUDIBLE - - -/datum/emote/brain/flash - key = "flash" - message = "blinks their lights." - - -/datum/emote/brain/notice - key = "notice" - message = "plays a loud tone." - emote_type = EMOTE_AUDIBLE - - -/datum/emote/brain/whistle - key = "whistle" - key_third_person = "whistles" - message = "whistles." - emote_type = EMOTE_AUDIBLE diff --git a/code/modules/mob/living/brain/life.dm b/code/modules/mob/living/brain/life.dm index ec65a88273e..f830572169b 100644 --- a/code/modules/mob/living/brain/life.dm +++ b/code/modules/mob/living/brain/life.dm @@ -28,11 +28,8 @@ return 1 //Handling EMP effect in the Life(), it's made VERY simply, and has some additional effects handled elsewhere - if(emp_damage) //This is pretty much a damage type only used by MMIs, dished out by the emp_act - if(!(container && istype(container, /obj/item/mmi))) - emp_damage = 0 - else - emp_damage = round(emp_damage,1)//Let's have some nice numbers to work with + if(emp_damage) + emp_damage = round(emp_damage,1)//Let's have some nice numbers to work with switch(emp_damage) if(31 to INFINITY) emp_damage = 30//Let's not overdo it @@ -110,17 +107,3 @@ interactee?.check_eye(src) return 1 - - -/*/mob/living/brain/emp_act(severity) - if(!(container && istype(container, /obj/item/mmi))) - return - else - switch(severity) - if(1) - emp_damage += rand(20,30) - if(2) - emp_damage += rand(10,20) - if(3) - emp_damage += rand(0,10) - ..()*/ diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 6a4f3d6ef30..059b33bad8c 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -64,7 +64,7 @@ return shock_damage -/mob/living/carbon/vomit() +/mob/living/carbon/proc/vomit() if(stat == DEAD) //Corpses don't puke return @@ -72,25 +72,23 @@ return TIMER_COOLDOWN_START(src, COOLDOWN_PUKE, 40 SECONDS) //5 seconds before the actual action plus 35 before the next one. - to_chat(src, "You feel like you are about to throw up!") + to_chat(src, span_warning("You feel like you are about to throw up!")) addtimer(CALLBACK(src, PROC_REF(do_vomit)), 5 SECONDS) - /mob/living/carbon/proc/do_vomit() adjust_stagger(3 SECONDS) add_slowdown(3) - visible_message("[src] throws up!","You throw up!", null, 5) + visible_message(span_warning("[src] throws up!"), span_warning("You throw up!"), null, 5) playsound(loc, 'sound/effects/splat.ogg', 25, TRUE, 7) var/turf/location = loc - if (istype(location, /turf)) + if(istype(location, /turf)) location.add_vomit_floor(src, 1) adjust_nutrition(-40) adjustToxLoss(-3) - /mob/living/carbon/proc/help_shake_act(mob/living/carbon/shaker) if(health < get_crit_threshold()) return diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 0b5bef65ddf..e243284b25b 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -9,12 +9,11 @@ // Only make the limb drop if it's not too damaged if(prob(100 - E.get_damage())) // Override the current limb status - //E.droplimb() // RUTGMC DELETION - E.droplimb(silent = TRUE) // RUTGMC ADDITION START + E.droplimb(silent = TRUE) visible_message(span_warning("[name] explodes violently into a bloody mess!"), span_highdanger("You explode violently into a bloody mess!"), - span_warning("You hear a terrible sound of breaking bones and ripping flesh!"), 3) // RUTGMC EDITION END + span_warning("You hear a terrible sound of breaking bones and ripping flesh!"), 3) if(is_a_synth) spawn_gibs() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index fca982b98c4..c8ec8344ffe 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -646,19 +646,17 @@ return FALSE return ..() - ///get_eye_protection() ///Returns a number between -1 to 2 /mob/living/carbon/human/get_eye_protection() var/number = 0 - if(!species.has_organ["eyes"]) return 2//No eyes, can't hurt them. + if(!species.has_organ["eyes"]) + return 2//No eyes, can't hurt them. var/datum/internal_organ/eyes/I = get_organ_slot(ORGAN_SLOT_EYES) if(!I) return 2 - if(I.robotic == ORGAN_ROBOT) - return 2 if(istype(head, /obj/item/clothing)) var/obj/item/clothing/C = head @@ -670,7 +668,6 @@ return number - /mob/living/carbon/human/abiotic(full_body = 0) if(full_body && ((src.l_hand && !( src.l_hand.flags_item & ITEM_ABSTRACT)) || (src.r_hand && !( src.r_hand.flags_item & ITEM_ABSTRACT)) || (src.back || src.wear_mask || src.head || src.shoes || src.w_uniform || src.wear_suit || src.glasses || src.wear_ear || src.gloves))) return 1 diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 69a3b8576da..3fb8014dbaa 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -25,14 +25,11 @@ var/health_deficiency = max(1 - (health / maxHealth) * 100, staminaloss) - //RUTGMC EDIT ADDITION BEGIN - Preds if(health_deficiency >= 50 && !(species?.species_flags & PARALYSE_RESISTANT)) -//RUTGMC EDIT ADDITION END add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN, TRUE, 0, NONE, TRUE, health_deficiency / 50) else remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN) - /mob/living/carbon/human/adjustBrainLoss(amount, silent = FALSE) if(status_flags & GODMODE) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 590f43c6feb..e5f06bcc801 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -61,14 +61,13 @@ Contains most of the procs that are called when a mob is attacked by something /mob/living/carbon/human/emp_act(severity) for(var/obj/O in src) - if(!O) continue + if(!O) + continue O.emp_act(severity) for(var/datum/limb/O in limbs) - if(O.limb_status & LIMB_DESTROYED) continue + if(O.limb_status & LIMB_DESTROYED) + continue O.emp_act(severity) - for(var/datum/internal_organ/I in O.internal_organs) - if(I.robotic == 0) continue - I.emp_act(severity) ..() /mob/living/carbon/human/has_smoke_protection() @@ -95,7 +94,6 @@ Contains most of the procs that are called when a mob is attacked by something var/datum/internal_organ/lungs/L = get_organ_slot(ORGAN_SLOT_LUNGS) L?.take_damage(1, TRUE) - //Returns 1 if the attack hit, 0 if it missed. /mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user, def_zone) @@ -412,7 +410,6 @@ Contains most of the procs that are called when a mob is attacked by something visible_message(span_notice("[user] ripped off [src]'s heart!"), span_notice("You ripped off [src]'s heart!")) remove_organ_slot(ORGAN_SLOT_HEART) var/obj/item/organ/heart/heart = new - heart.die() user.put_in_hands(heart) chestburst = 2 update_burst() diff --git a/code/modules/mob/living/carbon/human/human_status_procs.dm b/code/modules/mob/living/carbon/human/human_status_procs.dm index ac8f9e795be..31ee2e131fe 100644 --- a/code/modules/mob/living/carbon/human/human_status_procs.dm +++ b/code/modules/mob/living/carbon/human/human_status_procs.dm @@ -63,13 +63,17 @@ return //Machines don't throw up. return ..() +/mob/living/carbon/human/do_vomit() + . = ..() + var/datum/internal_organ/stomach/belly = get_organ_slot(ORGAN_SLOT_STOMACH) + for(var/datum/reagent/our_reagent in belly.reagents.reagent_list) + belly.reagents.remove_reagent(our_reagent.type, our_reagent.volume / rand(2, 5)) // vomit out some reagents from our stomach /mob/living/carbon/human/adjust_ear_damage(damage = 0, deaf = 0) if(isspeciessynthetic(src)) return return ..() - /mob/living/carbon/human/set_ear_damage(damage = 0, deaf = 0) if(isspeciessynthetic(src)) return diff --git a/code/modules/mob/living/carbon/human/life/handle_organs.dm b/code/modules/mob/living/carbon/human/life/handle_organs.dm index 45e7a08c54d..cec33540fe4 100644 --- a/code/modules/mob/living/carbon/human/life/handle_organs.dm +++ b/code/modules/mob/living/carbon/human/life/handle_organs.dm @@ -40,7 +40,7 @@ if(E.is_broken() && E.internal_organs && prob(15)) var/datum/internal_organ/I = pick(E.internal_organs) custom_pain("You feel broken bones moving in your [E.display_name]!", 1) - I.take_damage(rand(3,5)) + I.take_damage(rand(3, 5)) //Moving makes open wounds get infected much faster if(!(E.limb_wound_status & LIMB_WOUND_DISINFECTED) && E.brute_dam >= 20) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 71759dc4685..4e9529fc639 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -104,6 +104,7 @@ ORGAN_SLOT_HEART = /datum/internal_organ/heart, ORGAN_SLOT_LUNGS = /datum/internal_organ/lungs, ORGAN_SLOT_LIVER = /datum/internal_organ/liver, + ORGAN_SLOT_STOMACH = /datum/internal_organ/stomach, ORGAN_SLOT_KIDNEYS = /datum/internal_organ/kidneys, ORGAN_SLOT_BRAIN = /datum/internal_organ/brain, ORGAN_SLOT_APPENDIX = /datum/internal_organ/appendix, @@ -159,8 +160,8 @@ organless_human.limbs += new/datum/limb/foot/l_foot(new_l_leg, organless_human) organless_human.limbs += new/datum/limb/foot/r_foot(new_r_leg, organless_human) - for(var/organ in has_organ) - var/organ_type = has_organ[organ] + for(var/datum/internal_organ/organ AS in has_organ) + var/datum/internal_organ/organ_type = has_organ[organ] organless_human.internal_organs_by_name[organ] = new organ_type(organless_human) if(species_flags & ROBOTIC_LIMBS) @@ -168,9 +169,6 @@ if(robotic_limb.limb_status & LIMB_DESTROYED) continue robotic_limb.add_limb_flags(LIMB_ROBOT) - for(var/datum/internal_organ/my_cold_heart in organless_human.internal_organs) - my_cold_heart.mechanize() - /datum/species/proc/hug(mob/living/carbon/human/H, mob/living/target) if(H.zone_selected == "head") diff --git a/code/modules/mob/living/carbon/human/zombie.dm b/code/modules/mob/living/carbon/human/zombie.dm index fdf578343ba..f4230361587 100644 --- a/code/modules/mob/living/carbon/human/zombie.dm +++ b/code/modules/mob/living/carbon/human/zombie.dm @@ -14,8 +14,9 @@ ORGAN_SLOT_HEART = /datum/internal_organ/heart, ORGAN_SLOT_LUNGS = /datum/internal_organ/lungs, ORGAN_SLOT_LIVER = /datum/internal_organ/liver, + ORGAN_SLOT_STOMACH = /datum/internal_organ/stomach, ORGAN_SLOT_KIDNEYS = /datum/internal_organ/kidneys, - ORGAN_SLOT_BRAIN = /datum/internal_organ/brain/zombie, + ORGAN_SLOT_BRAIN = /datum/internal_organ/brain, ORGAN_SLOT_APPENDIX = /datum/internal_organ/appendix, ORGAN_SLOT_EYES = /datum/internal_organ/eyes ) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 2c363c84446..267107bda31 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -94,8 +94,6 @@ if(hallucination >= 20) // hallucinations require stacking before triggering handle_hallucinations() - - if(staminaloss > -max_stamina) handle_staminaloss() diff --git a/code/modules/mob/living/carbon/shock.dm b/code/modules/mob/living/carbon/shock.dm index 86d24b3aec9..62945f7a3e1 100644 --- a/code/modules/mob/living/carbon/shock.dm +++ b/code/modules/mob/living/carbon/shock.dm @@ -88,7 +88,8 @@ //Internal organs hurt too for(var/datum/internal_organ/O in M.internal_organs) - if(O.damage) traumatic_shock += O.damage * 1.5 + if(O.damage) + traumatic_shock += O.damage * 1.5 if(M.protection_aura) traumatic_shock -= 20 + M.protection_aura * 20 //-40 pain for SLs, -80 for Commanders diff --git a/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm b/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm index 473618de646..1b7690ac00a 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/carrier/abilities_carrier.dm @@ -8,7 +8,6 @@ GLOBAL_LIST_INIT(hugger_type_list, list( /obj/item/clothing/mask/facehugger/larval, /obj/item/clothing/mask/facehugger/combat/slash, -// /obj/item/clothing/mask/facehugger/combat/neuro, RU TGMC EDIT /obj/item/clothing/mask/facehugger/combat/acid, /obj/item/clothing/mask/facehugger/combat/resin, )) @@ -16,7 +15,6 @@ GLOBAL_LIST_INIT(hugger_type_list, list( GLOBAL_LIST_INIT(hugger_to_ammo, list( /obj/item/clothing/mask/facehugger/larval = /datum/ammo/xeno/hugger, /obj/item/clothing/mask/facehugger/combat/slash = /datum/ammo/xeno/hugger/slash, -// /obj/item/clothing/mask/facehugger/combat/neuro = /datum/ammo/xeno/hugger/neuro, RU TGMC EDIT /obj/item/clothing/mask/facehugger/combat/acid = /datum/ammo/xeno/hugger/acid, /obj/item/clothing/mask/facehugger/combat/resin = /datum/ammo/xeno/hugger/resin, )) @@ -25,7 +23,6 @@ GLOBAL_LIST_INIT(hugger_to_ammo, list( GLOBAL_LIST_INIT(hugger_images_list, list( LARVAL_HUGGER = image('icons/Xeno/actions.dmi', icon_state = LARVAL_HUGGER), CLAWED_HUGGER = image('icons/Xeno/actions.dmi', icon_state = CLAWED_HUGGER), -// NEURO_HUGGER = image('icons/Xeno/actions.dmi', icon_state = NEURO_HUGGER ), RU TGMC EDIT ACID_HUGGER = image('icons/Xeno/actions.dmi', icon_state = ACID_HUGGER), RESIN_HUGGER = image('icons/Xeno/actions.dmi', icon_state = RESIN_HUGGER), )) @@ -443,7 +440,7 @@ GLOBAL_LIST_INIT(hugger_images_list, list( victim.apply_damage(stamina_dmg, STAMINA) var/datum/internal_organ/O - for(var/i in list(ORGAN_SLOT_HEART, ORGAN_SLOT_LUNGS, ORGAN_SLOT_LIVER)) + for(var/i in list(ORGAN_SLOT_HEART, ORGAN_SLOT_LUNGS, ORGAN_SLOT_LIVER, ORGAN_SLOT_STOMACH)) O = victim.get_organ_slot(i) O.take_damage(debuff, TRUE) diff --git a/code/modules/mob/living/carbon/xenomorph/embryo.dm b/code/modules/mob/living/carbon/xenomorph/embryo.dm index 85dccb814ea..33435bd6947 100644 --- a/code/modules/mob/living/carbon/xenomorph/embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/embryo.dm @@ -17,7 +17,6 @@ var/hivenumber = XENO_HIVE_NORMAL var/admin = FALSE - /obj/item/alien_embryo/Initialize(mapload) . = ..() if(!isliving(loc)) @@ -221,7 +220,7 @@ var/mob/living/carbon/human/H = victim H.apply_damage(200, BRUTE, H.get_limb("chest"), updating_health = TRUE) //lethal armor ignoring brute damage var/datum/internal_organ/O - for(var/i in list(ORGAN_SLOT_HEART, ORGAN_SLOT_LUNGS, ORGAN_SLOT_LIVER, ORGAN_SLOT_KIDNEYS, ORGAN_SLOT_APPENDIX)) //Bruise all torso internal organs + for(var/i in list(ORGAN_SLOT_HEART, ORGAN_SLOT_LUNGS, ORGAN_SLOT_LIVER, ORGAN_SLOT_KIDNEYS, ORGAN_SLOT_APPENDIX, ORGAN_SLOT_STOMACH)) //Bruise all torso internal organs O = H.get_organ_slot(i) if(!H.mind && !H.client) //If we have no client or mind, permadeath time; remove the organs. Mainly for the NPC colonist bodies @@ -233,7 +232,6 @@ new /datum/wound/internal_bleeding(15, chest) //Apply internal bleeding to chest chest.fracture() - victim.chestburst = 2 victim.update_burst() log_combat(src, null, "chestbursted as a larva.") diff --git a/code/modules/mob/living/carbon/xenomorph/xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/xenomorph.dm index 34a00f520cb..70f247decc9 100644 --- a/code/modules/mob/living/carbon/xenomorph/xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/xenomorph.dm @@ -366,9 +366,6 @@ /mob/living/carbon/xenomorph/get_eye_protection() return 2 -/mob/living/carbon/xenomorph/vomit() - return - /mob/living/carbon/xenomorph/reagent_check(datum/reagent/R) //For the time being they can't metabolize chemicals. return TRUE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2ed59ba3a5d..980e0f8f9cf 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -619,11 +619,6 @@ below 100 is not dizzy var/datum/action/A = X A.update_button_icon() - -/mob/living/proc/vomit() - return - - /mob/living/proc/take_over(mob/M, bypass) if(!M.mind) to_chat(M, span_warning("You don't have a mind.")) diff --git a/code/modules/mob/living/living_health_procs.dm b/code/modules/mob/living/living_health_procs.dm index 73e629c7d0b..99b1f70b986 100644 --- a/code/modules/mob/living/living_health_procs.dm +++ b/code/modules/mob/living/living_health_procs.dm @@ -324,7 +324,6 @@ return ..() - /mob/living/carbon/human/revive(admin_revive = FALSE) restore_all_organs() @@ -350,6 +349,8 @@ I.heal_organ_damage(I.damage) reagents.clear_reagents() //and clear all reagents in them + var/datum/internal_organ/stomach/belly = get_organ_slot(ORGAN_SLOT_STOMACH) + belly.reagents.clear_reagents() REMOVE_TRAIT(src, TRAIT_UNDEFIBBABLE, TRAIT_UNDEFIBBABLE) REMOVE_TRAIT(src, TRAIT_PSY_DRAINED, TRAIT_PSY_DRAINED) dead_ticks = 0 @@ -358,7 +359,6 @@ update_hair() return ..() - /mob/living/carbon/xenomorph/revive(admin_revive = FALSE) set_plasma(xeno_caste.plasma_max) sunder = 0 diff --git a/code/modules/organs/_organ.dm b/code/modules/organs/_organ.dm new file mode 100644 index 00000000000..e1153728b13 --- /dev/null +++ b/code/modules/organs/_organ.dm @@ -0,0 +1,78 @@ +/datum/internal_organ + var/name = "organ" + /// Reference to the mob owning the organs + var/mob/living/carbon/human/owner = null + /// Reference to the limb we're inside of + var/datum/limb/parent_limb = BODY_ZONE_CHEST + /// amount of damage to the organ + var/damage = 0 + /// amount of damage after which the organ gets bruised flag + var/min_bruised_damage = 10 + /// amount of damage after which the organ gets broken flag + var/min_broken_damage = 30 + /// State of the organ + var/organ_status = ORGAN_HEALTHY + /// What slot does it go in? + var/slot + /// Will peri affect this organ? Thus ignores eyes, ears and brain + var/peri_effect = FALSE + +//This is used in the create_organs() which transfers human datums to organs +/datum/internal_organ/New(mob/living/carbon/carbon_mob) + ..() + if(!istype(carbon_mob)) + return + + carbon_mob.internal_organs |= src + owner = carbon_mob + + var/mob/living/carbon/human/human = carbon_mob + var/datum/limb/limb = human.get_limb(parent_limb) + LAZYDISTINCTADD(limb.internal_organs, src) + +/datum/internal_organ/Destroy() + clean_owner() + return ..() + +///Signal handler to prevent hard del +/datum/internal_organ/proc/clean_owner() + SIGNAL_HANDLER + owner = null + +/datum/internal_organ/proc/take_damage(amount, silent = FALSE) + if(SSticker.mode?.flags_round_type & MODE_NO_PERMANENT_WOUNDS) + return + if(amount <= 0) + heal_organ_damage(-amount) + return + damage += amount + + var/datum/limb/parent = owner.get_limb(parent_limb) + if(!silent) + owner.custom_pain("Something inside your [parent.display_name] hurts a lot.", 1) + set_organ_status() + +/datum/internal_organ/proc/heal_organ_damage(amount) + damage = max(damage - amount, 0) + set_organ_status() + +/// Set the correct organ state +/datum/internal_organ/proc/set_organ_status() + if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/peridaxon) >= 0.1 && peri_effect) //0.1 just in case + if(organ_status != ORGAN_HEALTHY) + organ_status = ORGAN_HEALTHY + return TRUE + return FALSE + else if(damage > min_broken_damage) + if(organ_status != ORGAN_BROKEN) + organ_status = ORGAN_BROKEN + return TRUE + return FALSE + else if(damage > min_bruised_damage) + if(organ_status != ORGAN_BRUISED) + organ_status = ORGAN_BRUISED + return TRUE + return FALSE + else if(organ_status != ORGAN_HEALTHY) + organ_status = ORGAN_HEALTHY + return TRUE diff --git a/code/modules/organs/limb_objects.dm b/code/modules/organs/limb_objects.dm index 009885c5dcb..d3ca45f6c69 100644 --- a/code/modules/organs/limb_objects.dm +++ b/code/modules/organs/limb_objects.dm @@ -1,4 +1,3 @@ - /obj/item/limb icon = 'icons/mob/human_races/r_human.dmi' item_icons = list( diff --git a/code/modules/organs/limbs.dm b/code/modules/organs/limbs.dm index 4777b1465cf..84fe689a4c8 100644 --- a/code/modules/organs/limbs.dm +++ b/code/modules/organs/limbs.dm @@ -185,7 +185,7 @@ if(internal_organs && ((sharp && brute >= 10) || brute >= 20) && prob(5)) //Damage an internal organ var/datum/internal_organ/I = pick(internal_organs) - I.take_damage(brute / 2) + I.get_damage(brute / 2) brute -= brute / 2 RU TGMC EDIT */ if(limb_status & LIMB_BROKEN && prob(40) && brute) @@ -506,12 +506,11 @@ Note that amputating the affected organ does in fact remove the infection from t owner.adjustToxLoss(1) if (prob(1)) to_chat(owner, span_notice("You have a high fever!")) -//Not technically a germ effect, but derived from it + //Not technically a germ effect, but derived from it if(limb_status & LIMB_NECROTIZED) for(var/datum/internal_organ/organ AS in internal_organs) organ.take_damage(0.2, silent = TRUE) //1 point every 10 seconds, 100 seconds to bruise, five minutes to broken. - ///Updating wounds. Handles natural damage healing from limb treatments and processes internal wounds /datum/limb/proc/update_wounds(limb_regen_penalty = 1) diff --git a/code/modules/organs/organ_alien.dm b/code/modules/organs/organ_alien.dm deleted file mode 100644 index 9f67598b0f4..00000000000 --- a/code/modules/organs/organ_alien.dm +++ /dev/null @@ -1,76 +0,0 @@ -//XENOMORPH ORGANS -/datum/internal_organ/xenos/eggsac - name = "egg sac" - parent_limb = "groin" - removed_type = /obj/item/organ/xenos/eggsac - -/datum/internal_organ/xenos/plasmavessel - name = "plasma vessel" - parent_limb = "chest" - removed_type = /obj/item/organ/xenos/plasmavessel - var/stored_plasma = 0 - var/max_plasma = 500 - -/datum/internal_organ/xenos/plasmavessel/queen - name = "bloated plasma vessel" - stored_plasma = 200 - max_plasma = 500 - -/datum/internal_organ/xenos/plasmavessel/sentinel - stored_plasma = 100 - max_plasma = 250 - -/datum/internal_organ/xenos/plasmavessel/hunter - name = "tiny plasma vessel" - stored_plasma = 100 - max_plasma = 150 - -/datum/internal_organ/xenos/acidgland - name = "acid gland" - parent_limb = "head" - removed_type = /obj/item/organ/xenos/acidgland - -/datum/internal_organ/xenos/hivenode - name = "hive node" - parent_limb = "chest" - removed_type = /obj/item/organ/xenos/hivenode - -/datum/internal_organ/xenos/resinspinner - name = "resin spinner" - parent_limb = "head" - removed_type = /obj/item/organ/xenos/resinspinner - -/obj/item/organ/xenos - name = "xeno organ" - icon = 'icons/effects/blood.dmi' - desc = "It smells like an accident in a chemical factory." - -/obj/item/organ/xenos/eggsac - name = "egg sac" - icon_state = "xgibmid1" - organ_tag = "egg sac" - organ_type = /datum/internal_organ/xenos/eggsac - -/obj/item/organ/xenos/plasmavessel - name = "plasma vessel" - icon_state = "xgibdown1" - organ_tag = "plasma vessel" - organ_type = /datum/internal_organ/xenos/plasmavessel - -/obj/item/organ/xenos/acidgland - name = "acid gland" - icon_state = "xgibtorso" - organ_tag = "acid gland" - organ_type = /datum/internal_organ/xenos/acidgland - -/obj/item/organ/xenos/hivenode - name = "hive node" - icon_state = "xgibmid2" - organ_tag = "hive node" - organ_type = /datum/internal_organ/xenos/hivenode - -/obj/item/organ/xenos/resinspinner - name = "hive node" - icon_state = "xgibmid2" - organ_tag = "resin spinner" - organ_type = /datum/internal_organ/xenos/resinspinner diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm deleted file mode 100644 index 7cd45adcf08..00000000000 --- a/code/modules/organs/organ_internal.dm +++ /dev/null @@ -1,403 +0,0 @@ - -/**************************************************** - INTERNAL ORGANS -****************************************************/ - - -/datum/internal_organ - var/name = "organ" - var/mob/living/carbon/human/owner = null - var/vital //Lose a vital limb, die immediately. - var/damage = 0 // amount of damage to the organ - var/min_bruised_damage = 10 - var/min_broken_damage = 30 - var/parent_limb = "chest" - var/robotic = 0 //1 for 'assisted' organs (e.g. pacemaker), 2 for actual cyber organ. - var/removed_type //When removed, forms this object. - var/robotic_type //robotic version of removed_type, used in mechanize(). - var/obj/item/organ/organ_holder // If not in a body, held in this item. - var/list/transplant_data - var/organ_id - /// State of the organ - var/organ_status = ORGAN_HEALTHY - var/peri_effect = FALSE - -/datum/internal_organ/process() - return 0 - -/datum/internal_organ/Destroy() - owner = null - organ_holder = null - return ..() - -/datum/internal_organ/New(mob/living/carbon/carbon_mob) - ..() - if(!istype(carbon_mob)) - return - - carbon_mob.internal_organs |= src - owner = carbon_mob - RegisterSignal(owner, COMSIG_QDELETING, PROC_REF(clean_owner)) - - if(!ishuman(carbon_mob)) - return - var/mob/living/carbon/human/human = carbon_mob - var/datum/limb/limb = human.get_limb(parent_limb) - LAZYDISTINCTADD(limb.internal_organs, src) - -///Signal handler to prevent hard del -/datum/internal_organ/proc/clean_owner() - SIGNAL_HANDLER - owner = null - -/datum/internal_organ/proc/take_damage(amount, silent= FALSE) - if(SSticker.mode?.flags_round_type & MODE_NO_PERMANENT_WOUNDS) - return - if(amount <= 0) - heal_organ_damage(-amount) - return - if(robotic == ORGAN_ROBOT) - damage += (amount * 0.8) - else - damage += amount - - var/datum/limb/parent = owner.get_limb(parent_limb) - if (!silent) - owner.custom_pain("Something inside your [parent.display_name] hurts a lot.", 1) - set_organ_status() - -/// Set the correct organ state -/datum/internal_organ/proc/set_organ_status() - if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/peridaxon) >= 0.1 && peri_effect) //0.1 just in case - if(organ_status != ORGAN_HEALTHY) - organ_status = ORGAN_HEALTHY - return TRUE - return FALSE - if(damage > min_broken_damage) - if(organ_status != ORGAN_BROKEN) - organ_status = ORGAN_BROKEN - return TRUE - return FALSE - if(damage > min_bruised_damage) - if(organ_status != ORGAN_BRUISED) - organ_status = ORGAN_BRUISED - return TRUE - return FALSE - if(organ_status != ORGAN_HEALTHY) - organ_status = ORGAN_HEALTHY - return TRUE - -/datum/internal_organ/proc/heal_organ_damage(amount) - damage = max(damage - amount, 0) - set_organ_status() - -/datum/internal_organ/proc/emp_act(severity) - switch(robotic) - if(0) - return - if(1) - switch (severity) - if (1.0) - take_damage(20,0) - return - if (2.0) - take_damage(7,0) - return - if(3.0) - take_damage(3,0) - return - if(2) - switch (severity) - if (1.0) - take_damage(40,0) - return - if (2.0) - take_damage(15,0) - return - if(3.0) - take_damage(10,0) - return - -/datum/internal_organ/proc/mechanize() //Being used to make robutt hearts, etc - if(robotic_type) - robotic = ORGAN_ROBOT - removed_type = robotic_type - - -/datum/internal_organ/proc/mechassist() //Used to add things like pacemakers, etc - robotic = ORGAN_ASSISTED - min_bruised_damage = 15 - min_broken_damage = 35 - -/**************************************************** - INTERNAL ORGANS TYPES -****************************************************/ - -/datum/internal_organ/heart // This is not set to vital because death immediately occurs in blood.dm if it is removed. Also, all damage effects are handled there. - name = "heart" - parent_limb = "chest" - removed_type = /obj/item/organ/heart - robotic_type = /obj/item/organ/heart/prosthetic - organ_id = ORGAN_HEART - peri_effect = TRUE - -/datum/internal_organ/heart/process() - . = ..() - - if(organ_status == ORGAN_BRUISED && prob(5)) - owner.emote("me", 1, "grabs at [owner.p_their()] chest!") - else if(organ_status == ORGAN_BROKEN && prob(20)) - owner.emote("me", 1, "clutches [owner.p_their()] chest!") - -/datum/internal_organ/heart/set_organ_status() - var/old_organ_status = organ_status - . = ..() - if(!.) - return - owner.max_stamina_buffer += (old_organ_status - organ_status) * 25 - owner.maxHealth += (old_organ_status - organ_status) * 20 - -/datum/internal_organ/heart/prosthetic //used by synthetic species - robotic = ORGAN_ROBOT - removed_type = /obj/item/organ/heart/prosthetic - -/datum/internal_organ/lungs - name = "lungs" - parent_limb = "chest" - removed_type = /obj/item/organ/lungs - robotic_type = /obj/item/organ/lungs/prosthetic - organ_id = ORGAN_LUNGS - peri_effect = TRUE - -/datum/internal_organ/lungs/process() - ..() - - if((organ_status == ORGAN_BRUISED && prob(5)) || (organ_status == ORGAN_BROKEN && prob(20))) - owner.emote("me", 1, "gasps for air!") - -/datum/internal_organ/lungs/set_organ_status() - . = ..() - if(!.) - return - owner.add_stamina_regen_modifier(name, organ_status * -0.40) // For example, bruised lungs will reduce stamina regen by 40%, broken by 80% - owner.add_movespeed_modifier(id = name, override = TRUE, multiplicative_slowdown = organ_status) // Slowdown added when the heart is damaged - - -/datum/internal_organ/lungs/take_damage(amount, silent= FALSE) - owner.adjust_Losebreath(amount) //Hits of 1 damage or less won't do anything due to how losebreath works, but any stronger and we'll get the wind knocked out of us for a bit. Mostly just flavor. - return ..() - -/datum/internal_organ/lungs/prosthetic - robotic = ORGAN_ROBOT - removed_type = /obj/item/organ/lungs/prosthetic - - -/datum/internal_organ/liver - name = "liver" - parent_limb = "chest" - removed_type = /obj/item/organ/liver - robotic_type = /obj/item/organ/liver/prosthetic - organ_id = ORGAN_LIVER - peri_effect = TRUE - ///lower value, higher resistance. - var/alcohol_tolerance = 0.005 - ///How fast we clean out toxins/toxloss. Adjusts based on organ damage. - var/filter_rate = 3 - -/datum/internal_organ/liver/process() - ..() - - //High toxins levels are dangerous if you aren't actively treating them. 100 seconds to hit bruised from this alone - if(owner.getToxLoss() >= (80 - 20 * organ_status)) - //Healthy liver suffers on its own - if (organ_status != ORGAN_BROKEN) - take_damage(0.2, TRUE) - //Damaged one shares the fun - else - var/datum/internal_organ/O = pick(owner.internal_organs) - O?.take_damage(0.2, TRUE) - - // Heal a bit if needed and we're not busy. This allows recovery from low amounts of toxins. - if(!owner.drunkenness && owner.getToxLoss() <= 15 && organ_status == ORGAN_HEALTHY) - heal_organ_damage(0.04) - - // Do some reagent filtering/processing. - for(var/datum/reagent/potential_toxin AS in owner.reagents.reagent_list) - //Liver helps clear out any toxins but with drawbacks if damaged - if(istype(potential_toxin, /datum/reagent/consumable/ethanol) || istype(potential_toxin, /datum/reagent/toxin)) - if(organ_status != ORGAN_HEALTHY) - owner.adjustToxLoss(0.3 * organ_status) - owner.reagents.remove_reagent(potential_toxin.type, potential_toxin.custom_metabolism * filter_rate * 0.1) - - //Heal toxin damage slowly if not damaged. If broken, increase it instead. - owner.adjustToxLoss((2 - filter_rate) * 0.1) - if(prob(organ_status)) //Just under once every three minutes while bruised, twice as often while broken. - owner.vomit() //No stomach, so the liver can cause vomiting instead. Stagger and slowdown plus feedback that something's wrong. - -/datum/internal_organ/liver/set_organ_status() - . = ..() - if(!.) - return - filter_rate = initial(filter_rate) - organ_status - -/datum/internal_organ/liver/prosthetic - robotic = ORGAN_ROBOT - removed_type = /obj/item/organ/liver/prosthetic - alcohol_tolerance = 0.003 - -/datum/internal_organ/kidneys - name = "kidneys" - parent_limb = "groin" - removed_type = /obj/item/organ/kidneys - robotic_type = /obj/item/organ/kidneys/prosthetic - organ_id = ORGAN_KIDNEYS - peri_effect = TRUE - ///Tracks the number of reagent/medicine datums we currently have - var/current_medicine_count = 0 - ///How many drugs we can take before they overwhelm us. Decreases with damage - var/current_medicine_cap = 5 - ///Additional medicine capacity given by the freyr module. - var/freyr_medicine_cap = 3 - ///Whether we were over cap the last time we checked. - var/old_overflow = FALSE - ///Total medicines added since last tick - var/new_medicines = 0 - ///Total medicines removed since last tick - var/removed_medicines = 0 - -/datum/internal_organ/kidneys/New(mob/living/carbon/carbon_mob) - . = ..() - if(!carbon_mob) - return - RegisterSignal(carbon_mob.reagents, COMSIG_NEW_REAGENT_ADD, PROC_REF(owner_added_reagent)) - RegisterSignal(carbon_mob.reagents, COMSIG_REAGENT_DELETING, PROC_REF(owner_removed_reagent)) - -/datum/internal_organ/kidneys/clean_owner() - if(owner?.reagents) - UnregisterSignal(owner.reagents, list(COMSIG_NEW_REAGENT_ADD, COMSIG_REAGENT_DELETING)) - return ..() - -///Signaled proc. Check if the added reagent was under reagent/medicine. If so, increment medicine counter and potentially notify owner. -/datum/internal_organ/kidneys/proc/owner_added_reagent(datum/source, reagent_type, amount) - SIGNAL_HANDLER - if(!ispath(reagent_type, /datum/reagent/medicine)) - return - new_medicines++ - -///Signaled proc. Check if the removed reagent was under reagent/medicine. If so, decrement medicine counter and potentially notify owner. -/datum/internal_organ/kidneys/proc/owner_removed_reagent(datum/source, reagent_type) - SIGNAL_HANDLER - if(!ispath(reagent_type, /datum/reagent/medicine)) - return - removed_medicines++ - -/datum/internal_organ/kidneys/set_organ_status() - . = ..() - if(!.) - return - current_medicine_cap = initial(current_medicine_cap) - 2 * organ_status - -/datum/internal_organ/kidneys/process() - ..() - - var/bypass = FALSE - - if(owner.bodytemperature <= 170) //No sense worrying about a chem cap if we're in cryo anyway. Still need to clear tick counts. - bypass = TRUE - - var/medicine_cap = current_medicine_cap - - if(SEND_SIGNAL(owner, COMSIG_LIVING_UPDATE_PLANE_BLUR) & COMPONENT_CANCEL_BLUR) - medicine_cap += freyr_medicine_cap - - current_medicine_count += new_medicines //We want to include medicines that were individually both added and removed this tick - var/overflow = current_medicine_count - medicine_cap //This catches any case where a reagent was added with volume below its metabolism - current_medicine_count -= removed_medicines //Otherwise, you can microdose infinite chems without kidneys complaining - - new_medicines = 0 - removed_medicines = 0 - - if(overflow < 1 || bypass) - if(old_overflow) - to_chat(owner, span_notice("You don't feel as overwhelmed by all the drugs any more.")) - old_overflow = FALSE - return - - if(!old_overflow) - to_chat(owner, span_warning("All the different drugs in you are starting to make you feel off...")) - old_overflow = TRUE - - owner.set_drugginess(3) - if(prob(overflow * (organ_status + 1) * 10)) - owner.Confused(2 SECONDS * (organ_status + 1)) - -/datum/internal_organ/kidneys/prosthetic - robotic = ORGAN_ROBOT - removed_type = /obj/item/organ/kidneys - -/datum/internal_organ/brain - name = "brain" - parent_limb = "head" - removed_type = /obj/item/organ/brain - robotic_type = /obj/item/organ/brain/prosthetic - vital = TRUE - organ_id = ORGAN_BRAIN - -/datum/internal_organ/brain/set_organ_status() - var/old_organ_status = organ_status - . = ..() - if(!.) - return - owner.set_skills(owner.skills.modifyAllRatings(old_organ_status - organ_status)) - if(organ_status >= ORGAN_BRUISED) - ADD_TRAIT(owner, TRAIT_DROOLING, BRAIN_TRAIT) - else - REMOVE_TRAIT(owner, TRAIT_DROOLING, BRAIN_TRAIT) - -/datum/internal_organ/brain/prosthetic //used by synthetic species - robotic = ORGAN_ROBOT - removed_type = /obj/item/organ/brain/prosthetic - -/datum/internal_organ/brain/xeno - removed_type = /obj/item/organ/brain/xeno - robotic_type = null - -/datum/internal_organ/brain/zombie - vital = FALSE - -/datum/internal_organ/eyes - name = "eyes" - parent_limb = "head" - removed_type = /obj/item/organ/eyes - robotic_type = /obj/item/organ/eyes/prosthetic - var/eye_surgery_stage = 0 //stores which stage of the eye surgery the eye is at - organ_id = ORGAN_EYES - -/datum/internal_organ/eyes/process() //Eye damage replaces the old eye_stat var. - ..() - if(organ_status == ORGAN_BRUISED) - owner.set_blurriness(20) - if(organ_status == ORGAN_BROKEN) - owner.set_blindness(20) - -/datum/internal_organ/eyes/prosthetic - robotic = ORGAN_ROBOT - removed_type = /obj/item/organ/eyes/prosthetic - - -/datum/internal_organ/appendix - name = "appendix" - parent_limb = "groin" - removed_type = /obj/item/organ/appendix - organ_id = ORGAN_APPENDIX - -/datum/internal_organ/proc/remove(mob/user) - - if(!removed_type) return 0 - - var/obj/item/organ/removed_organ = new removed_type(get_turf(user), src) - - if(istype(removed_organ)) - organ_holder = removed_organ - - return removed_organ diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm deleted file mode 100644 index 5bd3b540759..00000000000 --- a/code/modules/organs/organ_objects.dm +++ /dev/null @@ -1,225 +0,0 @@ -/obj/item/organ - name = "organ" - desc = "It looks like it probably just plopped out." - icon = 'icons/obj/items/organs.dmi' - item_icons = list( - slot_l_hand_str = 'icons/mob/inhands/items/bodyparts_left.dmi', - slot_r_hand_str = 'icons/mob/inhands/items/bodyparts_right.dmi', - ) - - icon_state = "appendix" - - max_integrity = 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/internal_organ // Used to spawn the relevant organ data when produced via a machine or spawn(). - var/datum/internal_organ/organ_data // Stores info when removed. - -/obj/item/organ/attack_self(mob/user as mob) - - // Convert it to an edible form, yum yum. - if(!robotic && user.a_intent == INTENT_HELP && user.zone_selected == "mouth") - bitten(user) - return - -/obj/item/organ/Initialize(mapload, organ_datum) - . = ..() - create_reagents(5) - if(organ_datum) - organ_data = organ_datum - else - organ_data = new organ_type() - if(!robotic) - START_PROCESSING(SSobj, src) - - -/obj/item/organ/Destroy() - if(!robotic) - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/organ/process() - - if(robotic) - STOP_PROCESSING(SSobj, 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/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer)) - return - - if(fresh && prob(40)) - fresh-- - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list - if(B) - var/turf/TU = get_turf(src) - var/list/L = list() - if(B.data["blood_DNA"]) - L = list(B.data["blood_DNA"] = B.data["blood_type"]) - TU.add_blood(L, B.color) - //blood_splatter(src,B,1) - - take_damage(rand(0,1)) - if(obj_integrity <= 0) - die() - -/obj/item/organ/proc/die() - name = "dead [initial(name)]" - if(dead_icon) icon_state = dead_icon - obj_integrity = 0 - STOP_PROCESSING(SSobj, src) - //TODO: Grey out the icon state. - //TODO: Inject an organ with peridaxon to make it alive again. - -// Brain is defined in brain_item.dm. -/obj/item/organ/heart - name = "heart" - icon_state = "heart-on" - organ_tag = ORGAN_SLOT_HEART - fresh = 6 // Juicy. - dead_icon = "heart-off" - organ_type = /datum/internal_organ/heart - -/obj/item/organ/lungs - name = "lungs" - icon_state = "lungs" - gender = PLURAL - organ_tag = ORGAN_SLOT_LUNGS - organ_type = /datum/internal_organ/lungs - -/obj/item/organ/kidneys - name = "kidneys" - icon_state = "kidneys" - gender = PLURAL - organ_tag = ORGAN_SLOT_KIDNEYS - organ_type = /datum/internal_organ/kidneys - -/obj/item/organ/eyes - name = "eyeballs" - icon_state = "eyes" - gender = PLURAL - organ_tag = ORGAN_SLOT_EYES - organ_type = /datum/internal_organ/eyes - var/eye_colour - -/obj/item/organ/liver - name = "liver" - icon_state = "liver" - organ_tag = ORGAN_SLOT_LIVER - organ_type = /datum/internal_organ/liver - -/obj/item/organ/appendix - name = "appendix" - icon_state = "appendix" - organ_type = /datum/internal_organ/appendix - organ_tag = ORGAN_SLOT_APPENDIX - -//These are here so they can be printed out via the fabricator. -/obj/item/organ/heart/prosthetic - name = "circulatory pump" - icon_state = "heart-prosthetic" - robotic = ORGAN_ROBOT - organ_type = /datum/internal_organ/heart/prosthetic - -/obj/item/organ/lungs/prosthetic - robotic = ORGAN_ROBOT - name = "gas exchange system" - icon_state = "lungs-prosthetic" - organ_type = /datum/internal_organ/lungs/prosthetic - -/obj/item/organ/kidneys/prosthetic - robotic = ORGAN_ROBOT - name = "prosthetic kidneys" - icon_state = "kidneys-prosthetic" - organ_type = /datum/internal_organ/kidneys/prosthetic - - -/obj/item/organ/eyes/prosthetic - robotic = ORGAN_ROBOT - name = "visual prosthesis" - icon_state = "eyes-prosthetic" - organ_type = /datum/internal_organ/eyes/prosthetic - -/obj/item/organ/liver/prosthetic - robotic = ORGAN_ROBOT - name = "toxin filter" - icon_state = "liver-prosthetic" - organ_type = /datum/internal_organ/liver/prosthetic - -/obj/item/organ/brain/prosthetic - robotic = ORGAN_ROBOT - name = "cyberbrain" - icon_state = "brain-prosthetic" - organ_type = /datum/internal_organ/brain/prosthetic - - -/obj/item/organ/proc/removed(mob/living/target,mob/living/user) - - if(!target || !user) - return - - if(organ_data.vital) - log_combat(user, target, "removed a vital organ ([src])", addition="(INTENT: [uppertext(user.a_intent)])") - target.death() - -/obj/item/organ/eyes/removed(mob/living/target,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(mob/living/target) - return - -/obj/item/organ/eyes/replaced(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 - - to_chat(user, span_notice("You take an experimental bite out of \the [src].")) - var/datum/reagent/blood/B = locate(/datum/reagent/blood) in reagents.reagent_list - if(B) - var/turf/TU = get_turf(src) - var/list/L = list() - if(B.data["blood_DNA"]) - L = list(B.data["blood_DNA"] = B.data["blood_type"]) - TU.add_blood(L, B.color) - - - user.temporarilyRemoveItemFromInventory(src) - var/obj/item/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) - - user.put_in_active_hand(O) - qdel(src) diff --git a/code/modules/organs/organ_props.dm b/code/modules/organs/organ_props.dm new file mode 100644 index 00000000000..c7054309aeb --- /dev/null +++ b/code/modules/organs/organ_props.dm @@ -0,0 +1,43 @@ +/obj/item/organ + name = "organ" + desc = "It looks like it probably just plopped out." + icon = 'icons/obj/items/organs.dmi' + item_icons = list( + slot_l_hand_str = 'icons/mob/inhands/items/bodyparts_left.dmi', + slot_r_hand_str = 'icons/mob/inhands/items/bodyparts_right.dmi', + ) + +/obj/item/organ/heart + name = "heart" + icon_state = "heart-on" + +/obj/item/organ/lungs + name = "lungs" + icon_state = "lungs" + gender = PLURAL + +/obj/item/organ/kidneys + name = "kidneys" + icon_state = "kidneys" + gender = PLURAL + +/obj/item/organ/liver + name = "liver" + icon_state = "liver" + +/obj/item/organ/appendix + name = "appendix" + icon_state = "appendix" + +/obj/item/organ/stomach + name = "stomach" + icon_state = "stomach" + +/obj/item/organ/eyes + name = "eyeballs" + icon_state = "eyes" + gender = PLURAL + +/obj/item/organ/brain + name = "brain" + icon_state = "brain2" diff --git a/code/modules/organs/organs.dm b/code/modules/organs/organs.dm new file mode 100644 index 00000000000..d19190ddc59 --- /dev/null +++ b/code/modules/organs/organs.dm @@ -0,0 +1,240 @@ +/datum/internal_organ/heart + name = "heart" + slot = ORGAN_SLOT_HEART + peri_effect = TRUE + +/datum/internal_organ/heart/process() + if(organ_status == ORGAN_BRUISED && prob(5)) + owner.emote("me", 1, "grabs at [owner.p_their()] chest!") + else if(organ_status == ORGAN_BROKEN && prob(20)) + owner.emote("me", 1, "clutches [owner.p_their()] chest!") + +/datum/internal_organ/heart/set_organ_status() + var/old_organ_status = organ_status + . = ..() + if(!.) + return + owner.max_stamina_buffer += (old_organ_status - organ_status) * 25 + owner.maxHealth += (old_organ_status - organ_status) * 20 + +/datum/internal_organ/lungs + name = "lungs" + slot = ORGAN_SLOT_LUNGS + peri_effect = TRUE + +/datum/internal_organ/lungs/process() + if((organ_status == ORGAN_BRUISED && prob(5)) || (organ_status == ORGAN_BROKEN && prob(20))) + owner.emote("me", 1, "gasps for air!") + +/datum/internal_organ/lungs/set_organ_status() + . = ..() + if(!.) + return + // For example, bruised lungs will reduce stamina regen by 40%, broken by 80% + owner.add_stamina_regen_modifier(name, organ_status * -0.40) + // Slowdown added when the heart is damaged + owner.add_movespeed_modifier(name, override = TRUE, multiplicative_slowdown = organ_status) + +//Hits of 1 damage or less won't do anything due to how losebreath works, but any stronger and we'll get the wind knocked out of us for a bit. Mostly just flavor. +/datum/internal_organ/lungs/take_damage(amount, silent = FALSE) + owner.adjust_Losebreath(amount) + return ..() + +/datum/internal_organ/kidneys + name = "kidneys" + slot = ORGAN_SLOT_KIDNEYS + parent_limb = BODY_ZONE_PRECISE_GROIN + peri_effect = TRUE + ///Tracks the number of reagent/medicine datums we currently have + var/current_medicine_count = 0 + ///How many drugs we can take before they overwhelm us. Decreases with damage + var/current_medicine_cap = 5 + ///Whether we were over cap the last time we checked. + var/old_overflow = FALSE + ///Total medicines added since last tick + var/new_medicines = 0 + ///Total medicines removed since last tick + var/removed_medicines = 0 + +/datum/internal_organ/kidneys/New(mob/living/carbon/carbon_mob) + . = ..() + if(!owner) + return + RegisterSignal(owner.reagents, COMSIG_NEW_REAGENT_ADD, PROC_REF(owner_added_reagent)) + RegisterSignal(owner.reagents, COMSIG_REAGENT_DELETING, PROC_REF(owner_removed_reagent)) + +/datum/internal_organ/kidneys/clean_owner() + if(owner?.reagents) + UnregisterSignal(owner.reagents, list(COMSIG_NEW_REAGENT_ADD, COMSIG_REAGENT_DELETING)) + return ..() + +///Signaled proc. Check if the added reagent was under reagent/medicine. If so, increment medicine counter and potentially notify owner. +/datum/internal_organ/kidneys/proc/owner_added_reagent(datum/source, reagent_type, amount) + SIGNAL_HANDLER + if(!ispath(reagent_type, /datum/reagent/medicine)) + return + new_medicines++ + +///Signaled proc. Check if the removed reagent was under reagent/medicine. If so, decrement medicine counter and potentially notify owner. +/datum/internal_organ/kidneys/proc/owner_removed_reagent(datum/source, reagent_type) + SIGNAL_HANDLER + if(!ispath(reagent_type, /datum/reagent/medicine)) + return + removed_medicines++ + +/datum/internal_organ/kidneys/set_organ_status() + . = ..() + if(!.) + return + current_medicine_cap = initial(current_medicine_cap) - 2 * organ_status + +/datum/internal_organ/kidneys/process() + current_medicine_count += new_medicines //We want to include medicines that were individually both added and removed this tick + var/overflow = current_medicine_count - current_medicine_cap //This catches any case where a reagent was added with volume below its metabolism + current_medicine_count -= removed_medicines //Otherwise, you can microdose infinite chems without kidneys complaining + + new_medicines = 0 + removed_medicines = 0 + + //No sense worrying about a chem cap if we're in cryo anyway. Still need to clear tick counts. + if(overflow < 1 || owner.bodytemperature <= 170) + if(old_overflow) + to_chat(owner, span_notice("You don't feel as overwhelmed by all the drugs any more.")) + old_overflow = FALSE + return + + if(!old_overflow) + to_chat(owner, span_warning("All the different drugs in you are starting to make you feel off...")) + old_overflow = TRUE + + owner.set_drugginess(3) + if(prob(overflow * (organ_status + 1) * 10)) + owner.Confused(2 SECONDS * (organ_status + 1)) + +/datum/internal_organ/liver + name = "liver" + slot = ORGAN_SLOT_LIVER + peri_effect = TRUE + ///lower value, higher resistance. + var/alcohol_tolerance = 0.005 + ///How fast we clean out toxins/toxloss. Adjusts based on organ damage. + var/filter_rate = 3 + +/datum/internal_organ/liver/process() + //High toxins levels are dangerous if you aren't actively treating them. 100 seconds to hit bruised from this alone + if(owner.getToxLoss() >= (80 - 20 * organ_status)) + //Healthy liver suffers on its own + if(organ_status != ORGAN_BROKEN) + take_damage(0.2, TRUE) + //Damaged one shares the fun + else + var/datum/internal_organ/O = pick(owner.internal_organs) + O?.take_damage(0.2, TRUE) + + // Heal a bit if needed and we're not busy. This allows recovery from low amounts of toxins. + if(!owner.drunkenness && owner.getToxLoss() <= 15 && organ_status == ORGAN_HEALTHY) + heal_organ_damage(0.04) + + // Do some reagent filtering/processing. + for(var/datum/reagent/potential_toxin AS in owner.reagents.reagent_list) + //Liver helps clear out any toxins but with drawbacks if damaged + if(istype(potential_toxin, /datum/reagent/consumable/ethanol) || istype(potential_toxin, /datum/reagent/toxin)) + if(organ_status != ORGAN_HEALTHY) + owner.adjustToxLoss(0.3 * organ_status) + owner.reagents.remove_reagent(potential_toxin.type, potential_toxin.custom_metabolism * filter_rate * 0.1) + + //Heal toxin damage slowly if not damaged. If broken, increase it instead. + owner.adjustToxLoss((2 - filter_rate) * 0.1) + if(prob(organ_status)) //Just under once every three minutes while bruised, twice as often while broken. + owner.vomit() //No stomach, so the liver can cause vomiting instead. Stagger and slowdown plus feedback that something's wrong. + +/datum/internal_organ/liver/set_organ_status() + . = ..() + if(!.) + return + filter_rate = initial(filter_rate) - organ_status + +/datum/internal_organ/appendix + name = "appendix" + slot = ORGAN_SLOT_APPENDIX + parent_limb = BODY_ZONE_PRECISE_GROIN + peri_effect = TRUE + +/datum/internal_organ/stomach + name = "stomach" + slot = ORGAN_SLOT_STOMACH + peri_effect = TRUE + ///The rate that the stomach will transfer reagents to the body + var/metabolism_efficiency = 0.05 // the lowest we should go is 0.025 + /// Our reagents + var/datum/reagents/reagents = new /datum/reagents(1000) + +/datum/internal_organ/stomach/process() + var/mob/living/carbon/human/body = owner + + // digest food, send all reagents that can be metabolized to the body + for(var/datum/reagent/bit AS in reagents?.reagent_list) + //Do not transfer over more then we have + var/amount_max = bit.volume + + // Transfer the amount of reagents based on volume with a min amount of 1u + var/rate_minimum = max(bit.custom_metabolism, 0.25) + var/amount = min((round(metabolism_efficiency * amount_max, 0.05) + rate_minimum), amount_max) + + if(amount <= 0) + continue + + // transfer the reagents over to the body at the rate of the stomach metabolim + // this way the body is where all reagents that are processed and react + // the stomach manages how fast they are feed in a drip style + reagents.trans_to(body, amount) + + //If the stomach is not damage exit out + if(damage < min_bruised_damage) + return + + if(prob(0.0125 * damage) || damage > min_broken_damage && prob(0.05 * damage)) + body.vomit() + to_chat(body, span_warning("Your stomach reels in pain as you're incapable of holding down it's contents!")) + return + +/datum/internal_organ/eyes + name = "eyeballs" + slot = ORGAN_SLOT_EYES + parent_limb = BODY_ZONE_HEAD + ///stores which stage of the eye surgery the eye is at + var/eye_surgery_stage = 0 + +/datum/internal_organ/eyes/process() + if(organ_status == ORGAN_BRUISED) + owner.set_blurriness(20) + if(organ_status == ORGAN_BROKEN) + owner.set_blindness(20) + +/datum/internal_organ/brain + name = "brain" + parent_limb = BODY_ZONE_HEAD + var/mob/living/brain/brainmob = null + +/datum/internal_organ/brain/set_organ_status() + var/old_organ_status = organ_status + . = ..() + if(!.) + return + owner.set_skills(owner.skills.modifyAllRatings(old_organ_status - organ_status)) + if(organ_status >= ORGAN_BRUISED) + ADD_TRAIT(owner, TRAIT_DROOLING, BRAIN_TRAIT) + else + REMOVE_TRAIT(owner, TRAIT_DROOLING, BRAIN_TRAIT) + +// I'm not sure if this proc is even used +/datum/internal_organ/brain/proc/transfer_identity(mob/living/carbon/H) + name = "[H]'s brain" + brainmob = new(src) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.timeofhostdeath = H.timeofdeath + if(H.mind) + H.mind.transfer_to(brainmob) + + to_chat(brainmob, span_notice("You feel slightly disoriented. That's normal when you're just a brain.")) diff --git a/code/modules/predator/yautja/chems.dm b/code/modules/predator/yautja/chems.dm index 5143326824e..ea8da893fc3 100644 --- a/code/modules/predator/yautja/chems.dm +++ b/code/modules/predator/yautja/chems.dm @@ -17,7 +17,7 @@ to_chat(L, span_userdanger("Something feels off!")) L.AdjustParalyzed(20) -/datum/reagent/thwei/on_mob_life(mob/living/L, metabolism) +/datum/reagent/thwei/on_mob_life(mob/living/carbon/L, metabolism) . = ..() if(isyautja(L)) L.blood_volume += 3 diff --git a/code/modules/reagents/holder.dm b/code/modules/reagents/holder.dm index 0d64f8bfc9f..6b7b3600819 100644 --- a/code/modules/reagents/holder.dm +++ b/code/modules/reagents/holder.dm @@ -146,35 +146,50 @@ * Transfer some stuff from this holder to a target object * * Arguments: - * * obj/target - Target to attempt transfer to + * * atom/target - Target to attempt transfer to * * amount - amount of reagent volume to transfer * * multiplier - multiplies amount of each reagent by this number * * preserve_data - if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. * * no_react - passed through to [/datum/reagents/proc/add_reagent] - * * mob/transfered_by - used for logging - * * remove_blacklisted - skips transferring of reagents with can_synth = FALSE - * * method - passed through to [/datum/reagents/proc/react_single] and [/datum/reagent/proc/on_transfer] - * * show_message - passed through to [/datum/reagents/proc/react_single] - * * round_robin - if round_robin=TRUE, so transfer 5 from 15 water, 15 sugar and 15 plasma becomes 10, 15, 15 instead of 13.3333, 13.3333 13.3333. Good if you hate floating point errors - */ -/datum/reagents/proc/trans_to(obj/target, amount = 1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred. - var/list/cached_reagents = reagent_list - if (!target || !total_volume) + * * transfer_to_stomach - does it goes to stomach like from pills and food? + * */ +/datum/reagents/proc/trans_to( + atom/target, + amount = 1, + multiplier = 1, + preserve_data = TRUE, + no_react = FALSE, + transfer_to_stomach = FALSE +) + if(!target || !total_volume) return - if (amount < 0) + if(amount < 0) return + var/list/cached_reagents = reagent_list var/datum/reagents/R if(istype(target, /datum/reagents)) R = target else - if(!target.reagents) + if(transfer_to_stomach && ishuman(target)) + var/mob/living/carbon/human/eater = target + var/datum/internal_organ/stomach/belly = eater.get_organ_slot(ORGAN_SLOT_STOMACH) + if(belly.organ_status != ORGAN_HEALTHY && prob(belly.damage * 3)) + var/expel_amount = round(amount, CHEMICAL_QUANTISATION_LEVEL) + if(expel_amount > 0 ) + eater.vomit() + var/datum/limb/chest/torso = eater.get_limb(belly.parent_limb) // eating with bruised stomach will get you infections + torso.germ_level += expel_amount * 15 // 10 units are 150 germ level and etc. + return + R = belly.reagents + else if(!target.reagents) return - R = target.reagents - amount = min(min(amount, total_volume), R.maximum_volume-R.total_volume) + else + R = target.reagents + amount = min(min(amount, total_volume), R.maximum_volume - R.total_volume) var/part = amount / total_volume var/trans_data = null - for(var/reagent in cached_reagents) + for(var/reagent AS in cached_reagents) var/datum/reagent/T = reagent var/transfer_amount = T.volume * part if(preserve_data) @@ -190,7 +205,7 @@ return amount /// Copies the reagents to the target object -/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1) +/datum/reagents/proc/copy_to(obj/target, amount = 1, multiplier = 1, preserve_data = 1) var/list/cached_reagents = reagent_list if(!target || !total_volume) return diff --git a/code/modules/reagents/reagents/drink.dm b/code/modules/reagents/reagents/drink.dm index a09b1a05436..5534f1abc76 100644 --- a/code/modules/reagents/reagents/drink.dm +++ b/code/modules/reagents/reagents/drink.dm @@ -491,7 +491,7 @@ adj_dizzy = 6 taste_description = "your brains smashed out by a lemon wrapped around a gold brick" -/datum/reagent/consumable/drink/gargle_blaster/on_mob_life(mob/living/L, metabolism) +/datum/reagent/consumable/drink/gargle_blaster/on_mob_life(mob/living/carbon/human/L, metabolism) switch(current_cycle) if(15 to 45) L.adjust_timed_status_effect(2 SECONDS, /datum/status_effect/speech/slurring/drunk) diff --git a/code/modules/reagents/reagents/medical.dm b/code/modules/reagents/reagents/medical.dm index 93979474cc0..b75b9108b1e 100644 --- a/code/modules/reagents/reagents/medical.dm +++ b/code/modules/reagents/reagents/medical.dm @@ -1,6 +1,3 @@ - -// All reagents related to medicine - /datum/reagent/medicine name = "Medicine" taste_description = "bitterness" @@ -1025,7 +1022,6 @@ if(prob(20)) L.hallucination += 15 - /datum/reagent/medicine/ultrazine/addiction_act_stage3(mob/living/L, metabolism) if(prob(10)) to_chat(L, span_warning("[pick("You need more.", "It's hard to go on like this.", "You want more. You need more.", "Just take another hit. Now.", "One more.")]")) @@ -1052,7 +1048,7 @@ L.adjustBrainLoss(0.1*effect_str, TRUE) if(prob(15) && ishuman(L)) var/mob/living/carbon/human/H = L - var/affected_organ = pick(ORGAN_SLOT_HEART, ORGAN_SLOT_LUNGS, ORGAN_SLOT_LIVER, ORGAN_SLOT_KIDNEYS) + var/affected_organ = pick(ORGAN_SLOT_HEART, ORGAN_SLOT_LUNGS, ORGAN_SLOT_LIVER, ORGAN_SLOT_KIDNEYS, ORGAN_SLOT_STOMACH) var/datum/internal_organ/I = H.get_organ_slot(affected_organ) I.take_damage(5.5 * effect_str) @@ -1254,19 +1250,19 @@ taste_description = "punishment" taste_multi = 8 -/datum/reagent/hypervene/on_mob_life(mob/living/L, metabolism) +/datum/reagent/hypervene/on_mob_life(mob/living/carbon/human/L, metabolism) L.reagent_shock_modifier -= PAIN_REDUCTION_HEAVY //Significant pain while metabolized. if(prob(5)) //causes vomiting L.vomit() return ..() -/datum/reagent/hypervene/overdose_process(mob/living/L, metabolism) +/datum/reagent/hypervene/overdose_process(mob/living/carbon/human/L, metabolism) L.apply_damages(effect_str, effect_str) if(prob(10)) //heavy vomiting L.vomit() L.reagent_shock_modifier -= PAIN_REDUCTION_VERY_HEAVY * 1.25//Massive pain. -/datum/reagent/hypervene/overdose_crit_process(mob/living/L, metabolism) +/datum/reagent/hypervene/overdose_crit_process(mob/living/carbon/human/L, metabolism) L.apply_damages(2*effect_str, 2*effect_str) if(prob(50)) //violent vomiting L.vomit() diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 3856839e9a6..8063e541617 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -81,20 +81,18 @@ success_sound = 'sound/misc/surgery/organ1.ogg' failure_sound = 'sound/misc/surgery/organ2.ogg' - /datum/surgery_step/internal/fix_organ/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected, checks_only) if(..()) if(affected.body_part == HEAD)//brain and eye damage is fixed by a separate surgery return SURGERY_CANNOT_USE for(var/datum/internal_organ/I in affected.internal_organs) - if(I.damage > 0 && I.robotic != ORGAN_ROBOT) + if(I.damage > 0) return SURGERY_CAN_USE return SURGERY_CANNOT_USE - /datum/surgery_step/internal/fix_organ/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected) for(var/datum/internal_organ/I in affected.internal_organs) - if(I?.damage > 0 && I.robotic != ORGAN_ROBOT) + if(I?.damage > 0) user.visible_message(span_notice("[user] starts treating damage to [target]'s [I.name] with the surgical membrane."), \ span_notice("You start treating damage to [target]'s [I.name] with the surgical membrane.") ) target.balloon_alert_to_viewers("Fixing...") @@ -104,7 +102,7 @@ /datum/surgery_step/internal/fix_organ/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected) for(var/datum/internal_organ/I in affected.internal_organs) - if(I?.damage > 0 && I.robotic != ORGAN_ROBOT) + if(I?.damage > 0) user.visible_message(span_notice("[user] treats damage to [target]'s [I.name] with surgical membrane."), \ span_notice("You treat damage to [target]'s [I.name] with surgical membrane.") ) @@ -126,57 +124,3 @@ I.take_damage(dam_amt,0) target.updatehealth() affected.update_wounds() - - - -/datum/surgery_step/internal/fix_organ_robotic //For artificial organs - allowed_tools = list( - /obj/item/stack/nanopaste = 100, - /obj/item/tool/surgery/bonegel = 30, - /obj/item/tool/screwdriver = 70, - ) - - min_duration = 60 - max_duration = 80 - -/datum/surgery_step/internal/fix_organ_robotic/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected, checks_only) - if(..()) - if(affected.body_part == HEAD)//brain and eye damage is fixed by a separate surgery - return SURGERY_CANNOT_USE - for(var/datum/internal_organ/I in affected.internal_organs) - if(I.damage > 0 && I.robotic == ORGAN_ROBOT) - return SURGERY_CAN_USE - return SURGERY_CANNOT_USE - -/datum/surgery_step/internal/fix_organ_robotic/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected) - for(var/datum/internal_organ/I in affected.internal_organs) - if(I?.damage > 0 && I.robotic == ORGAN_ROBOT) - user.visible_message(span_notice("[user] starts mending the damage to [target]'s [I.name]'s mechanisms."), \ - span_notice("You start mending the damage to [target]'s [I.name]'s mechanisms.") ) - - target.balloon_alert_to_viewers("Mending...") - target.custom_pain("The pain in your [affected.display_name] is living hell!", 1) - ..() - -/datum/surgery_step/internal/fix_organ_robotic/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected) - for(var/datum/internal_organ/I in affected.internal_organs) - if(I?.damage > 0 && I.robotic == ORGAN_ROBOT) - user.visible_message(span_notice("[user] repairs [target]'s [I.name] with [tool]."), \ - span_notice("You repair [target]'s [I.name] with [tool].") ) - I.damage = 0 - target.balloon_alert_to_viewers("Success") - return ..() - -/datum/surgery_step/internal/fix_organ_robotic/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected) - user.visible_message(span_warning("[user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.display_name] with \the [tool]!"), \ - span_warning("Your hand slips, gumming up the mechanisms inside of [target]'s [affected.display_name] with \the [tool]!")) - target.balloon_alert_to_viewers("Slipped!") - - target.adjustToxLoss(5) - affected.createwound(CUT, 5) - - for(var/datum/internal_organ/I in affected.internal_organs) - if(I) - I.take_damage(rand(3, 5), 0) - target.updatehealth() - affected.update_wounds() diff --git a/icons/obj/items/organs.dmi b/icons/obj/items/organs.dmi index 3cb475eceb9c0df019a582af56c44b63efd2b99f..b3cdbd539005c9d77bb2f1c5b024e544aa64aafe 100644 GIT binary patch literal 7427 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 L4c4mEu#5aJ!l9{y literal 3470 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 { `} onClick={() => act('effectLimb')} /> - -