From 37abd8f771f4b084d6426e413d21be8ef6685440 Mon Sep 17 00:00:00 2001 From: Matt Atlas Date: Fri, 13 Dec 2019 23:10:53 +0100 Subject: [PATCH] Brainmed Code Quality + Organ Scarring (#7645) Organ scarring has been made into a better system. New healthdoll. Other misc code cleanup attempts. Fixes #7647 --- code/__defines/mobs.dm | 2 +- code/controllers/subsystems/icon_cache.dm | 4 +- code/game/machinery/adv_med.dm | 51 +----- code/game/machinery/computer/Operating.dm | 30 +--- code/game/objects/items/devices/scanners.dm | 28 +-- code/modules/mob/death.dm | 4 +- .../mob/living/carbon/brain/brain_item.dm | 135 -------------- .../mob/living/carbon/human/examine.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 12 +- .../mob/living/carbon/human/human_damage.dm | 2 - .../mob/living/carbon/human/human_organs.dm | 25 +++ code/modules/mob/living/carbon/human/life.dm | 102 +++++------ .../living/carbon/human/species/species.dm | 3 +- code/modules/organs/blood.dm | 7 +- code/modules/organs/internal/_internal.dm | 17 +- code/modules/organs/internal/brain.dm | 166 ++++++++++++++++-- code/modules/organs/internal/heart.dm | 2 +- code/modules/organs/organ_external.dm | 2 + code/modules/organs/organ_icon.dm | 42 ++++- .../Chemistry-Reagents-Food-Drinks.dm | 2 +- code/modules/surgery/organs_internal.dm | 2 +- code/modules/surgery/other.dm | 6 +- .../mattatlas-goodcodequestionmarjk.yml | 42 +++++ icons/mob/screen1_health.dmi | Bin 0 -> 888 bytes 24 files changed, 356 insertions(+), 332 deletions(-) create mode 100644 html/changelogs/mattatlas-goodcodequestionmarjk.yml create mode 100644 icons/mob/screen1_health.dmi diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 5955f849247..5a1804262d8 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -90,7 +90,7 @@ //Organ defines #define PROCESS_ACCURACY 10 -#define DEFAULT_BLOOD_SPECIES 560 //Default blood for species +#define DEFAULT_BLOOD_AMOUNT 560 //Default blood amount in units //These are used Bump() code for living mobs, in the mob_bump_flag, mob_swap_flags, and mob_push_flags vars to determine whom can bump/swap with whom. #define HUMAN 1 diff --git a/code/controllers/subsystems/icon_cache.dm b/code/controllers/subsystems/icon_cache.dm index ce178b8b25b..dbb2108c6e0 100644 --- a/code/controllers/subsystems/icon_cache.dm +++ b/code/controllers/subsystems/icon_cache.dm @@ -36,8 +36,8 @@ var/list/human_icon_cache = list() var/list/tail_icon_cache = list() //key is [species.race_key][r_skin][g_skin][b_skin] var/list/light_overlay_cache = list() - // Cached body hair icons, used by resomi. - var/list/body_hair_cache = list() + // Cached limb icons, used by the damage health doll. + var/list/limb_icons_cache = list() // Cached human damage icons. var/list/damage_icon_parts = list() // Cached human body markings. diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index d58543a8587..7e3dfabb92b 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -336,28 +336,7 @@ if (!data["invalid"]) var/datum/reagents/R = occupant.bloodstr - var/brain_result - if(occupant.should_have_organ(BP_BRAIN)) - var/obj/item/organ/internal/brain/brain = occupant.internal_organs_by_name[BP_BRAIN] - if(!brain || occupant.stat == DEAD || (occupant.status_flags & FAKEDEATH)) - brain_result = 0 - else if(occupant.stat != DEAD) - brain_result = round(max(0,(1 - brain.damage/brain.max_damage)*100)) - else - brain_result = -1 - - switch(brain_result) - if(0) - brain_result = "none, patient is braindead" - if(-1) - brain_result = "ERROR - Nonstandard biology" - else - if(brain_result <= 50) - brain_result = "[brain_result]%" - else if(brain_result <= 80) - brain_result = "[brain_result]%" - else - brain_result = "[brain_result]%" + var/brain_result = occupant.get_brain_status() var/pulse_result if(occupant.should_have_organ(BP_HEART)) @@ -518,6 +497,9 @@ if(O.rejecting) wounds += "Shows symptoms of organ rejection." + if(O.get_scarring_level() > 0.01) + wounds += "[O.get_scarring_results()]." + data["hasWounds"] = length(wounds) ? 1 : 0 data["wounds"] = wounds organs += list(data) @@ -556,28 +538,7 @@ if (!occupant || !istype(occupant, /mob/living/carbon/human)) return var/mob/living/carbon/human/H = occupant - var/brain_result - if(H.should_have_organ(BP_BRAIN)) - var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[BP_BRAIN] - if(!brain || H.stat == DEAD || (H.status_flags & FAKEDEATH)) - brain_result = 0 - else if(H.stat != DEAD) - brain_result = round(max(0,(1 - brain.damage/brain.max_damage)*100)) - else - brain_result = -1 - - switch(brain_result) - if(0) - brain_result = "none, patient is braindead" - if(-1) - brain_result = "ERROR - Nonstandard biology" - else - if(brain_result <= 50) - brain_result = "[brain_result]%" - else if(brain_result <= 80) - brain_result = "[brain_result]%" - else - brain_result = "[brain_result]%" + var/brain_result = H.get_brain_status() var/list/occupant_data = list( "stationtime" = worldtime2text(), @@ -727,6 +688,8 @@ infection += "(being rejected)" var/necrotic = "" + if(i.get_scarring_level() > 0.01) + necrotic += ", [i.get_scarring_results()]" if(i.status & ORGAN_DEAD) necrotic = ", necrotic and decaying" diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index eb08706cc86..e8211a0f023 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -45,33 +45,9 @@ dat += "Close

" //| Update" if(src.table && (src.table.check_victim())) src.victim = src.table.victim - var/brain_result = "normal" - if(victim.should_have_organ(BP_BRAIN)) - var/obj/item/organ/internal/brain/brain = victim.internal_organs_by_name[BP_BRAIN] - if(!brain || victim.stat == DEAD || (victim.status_flags & FAKEDEATH)) - brain_result = "none, patient is braindead" - else if(victim.stat != DEAD) - if(istype(brain)) - switch(brain.get_current_damage_threshold()) - if(0) - brain_result = "normal" - if(1 to 2) - brain_result = "minor brain damage" - if(3 to 5) - brain_result = "weak" - if(6 to 8) - brain_result = "extremely weak" - if(9 to INFINITY) - brain_result = "fading" - else - brain_result = "ERROR - Hardware fault" - else - if(victim.isFBP()) - brain_result = "normal" - else - brain_result = "ERROR - Organ not recognized" - else - brain_result = "ERROR - Non-standard biology" + var/brain_result = victim.get_brain_status() + if(victim.isFBP()) + brain_result = "normal" dat += {" Patient Information:
Brain Activity: [brain_result]
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 2cd4ecb8084..749fac516e6 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -110,33 +110,7 @@ BREATH ANALYZER . += "[b]Scan results for \the [H]:[endb]" // Brain activity. - var/brain_result = "normal" - if(H.should_have_organ(BP_BRAIN)) - var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[BP_BRAIN] - if(!brain || H.stat == DEAD || (H.status_flags & FAKEDEATH)) - brain_result = "none, patient is braindead" - else if(H.stat != DEAD) - if(istype(brain)) - switch(brain.get_current_damage_threshold()) - if(0) - brain_result = "normal" - if(1 to 2) - brain_result = "minor brain damage" - if(3 to 5) - brain_result = "weak" - if(6 to 8) - brain_result = "extremely weak" - if(9 to INFINITY) - brain_result = "fading" - else - brain_result = "ERROR - Hardware fault" - else - if(H.isFBP()) - brain_result = "normal" - else - brain_result = "ERROR - Organ not recognized" - else - brain_result = "ERROR - Non-standard biology" + var/brain_result = H.get_brain_status() dat += "Brain activity: [brain_result]." if(H.stat == DEAD || (H.status_flags & FAKEDEATH)) diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 3b482901e7c..932b84f7c7c 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -78,7 +78,9 @@ drop_l_hand() if(healths) - healths.icon_state = "health7" + healths.overlays.Cut() // This is specific to humans but the relevant code is here; shouldn't mess with other mobs. + if("health7" in icon_states(healths.icon)) + healths.icon_state = "health7" timeofdeath = world.time if (isanimal(src)) diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 9006d7d955e..0a4f95aed85 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -16,95 +16,6 @@ /obj/item/organ/internal/brain/xeno/gain_trauma() return -/obj/item/organ/internal/brain/proc/clear_screen() - if (brainmob && brainmob.client) - brainmob.client.screen.Cut() - -/obj/item/organ/internal/brain/Destroy() - if(brainmob) - qdel(brainmob) - brainmob = null - return ..() - -/obj/item/organ/internal/brain/proc/transfer_identity(var/mob/living/carbon/H) - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.dna = H.dna.Clone() - brainmob.timeofhostdeath = H.timeofdeath - if(H.mind) - H.mind.transfer_to(brainmob) - - to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a [initial(src.name)].") - callHook("debrain", list(brainmob)) - -/obj/item/organ/internal/brain/examine(mob/user) // -- TLE - ..(user) - if(brainmob && brainmob.client)//if thar be a brain inside... the brain. - to_chat(user, "You can feel the small spark of life still left in this one.") - else - to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later..") - -/obj/item/organ/internal/brain/removed(var/mob/living/user) - - for(var/X in traumas) - var/datum/brain_trauma/BT = X - BT.on_lose(TRUE) - BT.owner = null - - var/mob/living/simple_animal/borer/borer = owner.has_brain_worms() - - if(borer) - borer.detatch() //Should remove borer if the brain is removed - RR - - var/obj/item/organ/internal/brain/B = src - if(istype(B) && istype(owner)) - B.transfer_identity(owner) - - ..() - -/obj/item/organ/internal/brain/replaced(var/mob/living/target) - - if(target.key) - target.ghostize() - - if(brainmob) - if(brainmob.mind) - brainmob.mind.transfer_to(target) - else - target.key = brainmob.key - - for(var/X in traumas) - var/datum/brain_trauma/BT = X - BT.owner = owner - BT.on_gain() - - ..() - -/obj/item/organ/internal/brain/proc/lobotomize(mob/user as mob) - lobotomized = 1 - - if(owner) - to_chat(owner, "As part of your brain is drilled out, you feel your past self, your memories, your very being slip away...") - to_chat(owner, "Your brain has been surgically altered to remove your memory recall. Your ability to recall your former life has been surgically removed from your brain, and while your brain is in this state you remember nothing that ever came before this moment.") - - else if(brainmob) - to_chat(brainmob, "As part of your brain is drilled out, you feel your past self, your memories, your very being slip away...") - to_chat(brainmob, "Your brain has been surgically altered to remove your memory recall. Your ability to recall your former life has been surgically removed from your brain, and while your brain is in this state you remember nothing that ever came before this moment.") - - return - -/obj/item/organ/internal/brain/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W,/obj/item/surgicaldrill)) - if(!can_lobotomize) - return - if(!lobotomized) - user.visible_message("[user] drills [src] deftly with [W] into the brain!") - lobotomize(user) - else - to_chat(user, "The brain has already been operated on!") - ..() - /obj/item/organ/internal/brain/slime name = "slime core" desc = "A complex, organic knot of jelly and crystalline particles." @@ -120,49 +31,3 @@ icon = 'icons/obj/wizard.dmi' icon_state = "scroll" can_lobotomize = 0 - - -////////////////////////////////////TRAUMAS//////////////////////////////////////// - -/obj/item/organ/internal/brain/proc/has_trauma_type(brain_trauma_type, consider_permanent = FALSE) - for(var/X in traumas) - var/datum/brain_trauma/BT = X - if(istype(BT, brain_trauma_type) && (consider_permanent || !BT.permanent)) - return BT - - -//Add a specific trauma -/obj/item/organ/internal/brain/proc/gain_trauma(datum/brain_trauma/trauma, permanent = FALSE, list/arguments) - var/trauma_type - if(ispath(trauma)) - trauma_type = trauma - traumas += new trauma_type(arglist(list(src, permanent) + arguments)) - else - traumas += trauma - trauma.permanent = permanent - -//Add a random trauma of a certain subtype -/obj/item/organ/internal/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, permanent = FALSE) - var/list/datum/brain_trauma/possible_traumas = list() - for(var/T in subtypesof(brain_trauma_type)) - var/datum/brain_trauma/BT = T - if(initial(BT.can_gain)) - possible_traumas += BT - - var/trauma_type = pick(possible_traumas) - traumas += new trauma_type(src, permanent) - -//Cure a random trauma of a certain subtype -/obj/item/organ/internal/brain/proc/cure_trauma_type(brain_trauma_type, cure_permanent = FALSE) - var/datum/brain_trauma/trauma = has_trauma_type(brain_trauma_type) - if(trauma && (cure_permanent || !trauma.permanent)) - qdel(trauma) - -/obj/item/organ/internal/brain/proc/cure_all_traumas(cure_permanent = FALSE, cure_type = "") - for(var/X in traumas) - var/datum/brain_trauma/trauma = X - if(trauma.cure_type == cure_type || cure_type == CURE_ADMIN) - if(cure_permanent || !trauma.permanent) - qdel(trauma) - if(cure_type != CURE_ADMIN) - break \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 9a6e7d12968..e0f756d80c0 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -59,7 +59,7 @@ msg += ", a [species.name]" msg += "!\n" - if (species && species.has_organ[BP_IPCTAG] && internal_organs_by_name[BP_IPCTAG]) + if (should_have_organ(BP_IPCTAG) && internal_organs_by_name[BP_IPCTAG]) msg += "[T.He] [T.is] wearing a tag designating them as Integrated Positronic Chassis [src.real_name].\n" //uniform diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c0c9238fd1a..63fb32fcd90 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1709,32 +1709,32 @@ /mob/living/carbon/human/proc/get_traumas() . = list() var/obj/item/organ/internal/brain/B = internal_organs_by_name[BP_BRAIN] - if(B && species && species.has_organ[BP_BRAIN] && !isipc(src)) + if(B && should_have_organ(BP_BRAIN) && !isipc(src)) . = B.traumas /mob/living/carbon/human/proc/has_trauma_type(brain_trauma_type, consider_permanent = FALSE) var/obj/item/organ/internal/brain/B = internal_organs_by_name[BP_BRAIN] - if(B && species && species.has_organ[BP_BRAIN] && !isipc(src)) + if(B && should_have_organ(BP_BRAIN) && !isipc(src)) . = B.has_trauma_type(brain_trauma_type, consider_permanent) /mob/living/carbon/human/proc/gain_trauma(datum/brain_trauma/trauma, permanent = FALSE, list/arguments) var/obj/item/organ/internal/brain/B = internal_organs_by_name[BP_BRAIN] - if(B && species && species.has_organ[BP_BRAIN] && !isipc(src)) + if(B && should_have_organ(BP_BRAIN) && !isipc(src)) . = B.gain_trauma(trauma, permanent, arguments) /mob/living/carbon/human/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, permanent = FALSE) var/obj/item/organ/internal/brain/B = internal_organs_by_name[BP_BRAIN] - if(B && species && species.has_organ[BP_BRAIN] && !isipc(src)) + if(B && should_have_organ(BP_BRAIN) && !isipc(src)) . = B.gain_trauma_type(brain_trauma_type, permanent) /mob/living/carbon/human/proc/cure_trauma_type(brain_trauma_type, cure_permanent = FALSE) var/obj/item/organ/internal/brain/B = internal_organs_by_name[BP_BRAIN] - if(B && species && species.has_organ[BP_BRAIN] && !isipc(src)) + if(B && should_have_organ(BP_BRAIN) && !isipc(src)) . = B.cure_trauma_type(brain_trauma_type, cure_permanent) /mob/living/carbon/human/proc/cure_all_traumas(cure_permanent = FALSE, cure_type = "") var/obj/item/organ/internal/brain/B = internal_organs_by_name[BP_BRAIN] - if(B && species && species.has_organ[BP_BRAIN] && !isipc(src)) + if(B && should_have_organ(BP_BRAIN) && !isipc(src)) . = B.cure_all_traumas(cure_permanent, cure_type) /mob/living/carbon/human/get_metabolism(metabolism) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 39f4c49c933..8a4d49d7522 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -6,8 +6,6 @@ stat = CONSCIOUS return - update_health_display() - health = maxHealth - getBrainLoss() //TODO: fix husking diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 5629f0d4ee8..f02d56060ce 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -206,3 +206,28 @@ if(!istype(heart) || !heart.is_working()) return TRUE return FALSE + +/mob/living/carbon/human/proc/get_brain_status() + var/brain_result + if(should_have_organ(BP_BRAIN)) + var/obj/item/organ/internal/brain/brain = internal_organs_by_name[BP_BRAIN] + if(!brain || stat == DEAD || (status_flags & FAKEDEATH)) + brain_result = 0 + else if(stat != DEAD) + brain_result = round(max(0,(1 - brain.damage/brain.max_damage)*100)) + else + brain_result = -1 + + switch(brain_result) + if(0) + brain_result = "none, patient is braindead" + if(-1) + brain_result = "ERROR - Nonstandard biology" + else + if(brain_result <= 50) + brain_result = "[brain_result]%" + else if(brain_result <= 80) + brain_result = "[brain_result]%" + else + brain_result = "[brain_result]%" + return brain_result diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index f4ccd93d644..714ae584921 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -878,10 +878,9 @@ if(!..()) return - if(stat == UNCONSCIOUS) - //Critical damage passage overlay - if(health < maxHealth/2) - var/ovr = "passage0" + if(stat != DEAD) + if(stat == UNCONSCIOUS && health < maxHealth/2) + var/ovr switch(health - maxHealth/2) if(-20 to -10) ovr = "passage1" @@ -908,22 +907,9 @@ damageoverlay.cut_overlay(last_brute_overlay) damageoverlay.add_overlay(ovr) last_brute_overlay = ovr - else - //Oxygen damage overlay - update_oxy_overlay() - - // Vampire frenzy overlay. - if (mind.vampire) - if (mind.vampire.status & VAMP_FRENZIED) - if (!last_frenzy_state) - damageoverlay.add_overlay("frenzyoverlay") - last_frenzy_state = TRUE - else if (last_frenzy_state) - damageoverlay.cut_overlay("frenzyoverlay") - last_frenzy_state = FALSE - else if (last_frenzy_state) - damageoverlay.cut_overlay("frenzyoverlay") - last_frenzy_state = FALSE + else + //Oxygen damage overlay + update_oxy_overlay() //Fire and Brute damage overlay (BSSR) var/hurtdamage = src.getBruteLoss() + src.getFireLoss() + damageoverlaytemp @@ -948,11 +934,43 @@ damageoverlay.cut_overlay(last_brute_overlay) damageoverlay.add_overlay(ovr) last_brute_overlay = ovr - else if (last_brute_overlay) - damageoverlay.cut_overlay(last_brute_overlay) - last_brute_overlay = null - update_health_display() + if(healths) + healths.overlays.Cut() + if (chem_effects[CE_PAINKILLER] > 100) + healths.icon_state = "health_numb" + else + // Generate a by-limb health display. + healths.icon_state = "blank" + + var/no_damage = 1 + var/trauma_val = 0 // Used in calculating softcrit/hardcrit indicators. + if(can_feel_pain()) + trauma_val = max(shock_stage,get_shock())/(species.total_health-100) + // Collect and apply the images all at once to avoid appearance churn. + var/list/health_images = list() + for(var/obj/item/organ/external/E in organs) + if(no_damage && (E.brute_dam || E.burn_dam)) + no_damage = 0 + health_images += E.get_damage_hud_image() + + // Apply a fire overlay if we're burning. + if(on_fire) + health_images += image('icons/mob/screen1_health.dmi',"burning") + + // Show a general pain/crit indicator if needed. + if(is_asystole()) + health_images += image('icons/mob/screen1_health.dmi',"hardcrit") + else if(trauma_val) + if(can_feel_pain()) + if(trauma_val > 0.7) + health_images += image('icons/mob/screen1_health.dmi',"softcrit") + if(trauma_val >= 1) + health_images += image('icons/mob/screen1_health.dmi',"hardcrit") + else if(no_damage) + health_images += image('icons/mob/screen1_health.dmi',"fullhealth") + + healths.overlays += health_images //Update hunger and thirst UI less often, its not important if((life_tick % 3 == 0)) @@ -1387,42 +1405,6 @@ if (client) hud_used.move_intent.update_move_icon(src) -/mob/living/carbon/human/proc/update_health_display() - if(!healths) - return - - var/new_state - if (stat == DEAD) - new_state = "health7" - else if (analgesic > 100) - new_state = "health_numb" - else - switch(hal_screwyhud) - if(1) - new_state = "health6" - if(2) - new_state = "health7" - else - //switch(health - halloss) - switch(health - get_shock()) - if(100 to INFINITY) - new_state = "health0" - if(80 to 100) - new_state = "health1" - if(60 to 80) - new_state = "health2" - if(40 to 60) - new_state = "health3" - if(20 to 40) - new_state = "health4" - if(0 to 20) - new_state = "health5" - else - new_state = "health6" - - if (healths.icon_state != new_state) - healths.icon_state = new_state - /mob/living/carbon/human/proc/update_oxy_overlay() var/new_oxy if(getOxyLoss()) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 383d738770d..17fedb12cf5 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -76,7 +76,7 @@ var/grab_mod = 1 // How easy it is to grab the species. Higher is harder to grab. var/metabolism_mod = 1 // Reagent metabolism modifier var/bleed_mod = 1 // How fast this species bleeds. - var/blood_volume = DEFAULT_BLOOD_SPECIES // Blood volume. + var/blood_volume = DEFAULT_BLOOD_AMOUNT // Blood volume. var/vision_flags = DEFAULT_SIGHT // Same flags as glasses. var/inherent_eye_protection // If set, this species has this level of inherent eye protection. @@ -137,6 +137,7 @@ // HUD data vars. var/datum/hud_data/hud var/hud_type + var/health_hud_intensity = 1 // Body/form vars. var/list/inherent_verbs // Species-specific verbs. diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 8d1255a9a24..6e03a7a3e62 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -9,13 +9,12 @@ if(vessel) return - vessel = new/datum/reagents(DEFAULT_BLOOD_SPECIES + 40) - vessel.my_atom = src + vessel = new/datum/reagents(species.blood_volume, src) if(species && species.flags & NO_BLOOD) //We want the var for safety but we can do without the actual blood. return - vessel.add_reagent("blood", DEFAULT_BLOOD_SPECIES) + vessel.add_reagent("blood", species.blood_volume) fixblood() //Resets blood data @@ -209,7 +208,7 @@ var/list/chems = list() chems = params2list(injected.data["trace_chem"]) for(var/C in chems) - src.reagents.add_reagent(C, (text2num(chems[C]) / DEFAULT_BLOOD_SPECIES) * amount)//adds trace chemicals to owner's blood + src.reagents.add_reagent(C, (text2num(chems[C]) / species.blood_volume) * amount)//adds trace chemicals to owner's blood reagents.update_total() //Transfers blood from reagents to vessel, respecting blood types compatability. diff --git a/code/modules/organs/internal/_internal.dm b/code/modules/organs/internal/_internal.dm index b3855545be4..6507efb70d5 100644 --- a/code/modules/organs/internal/_internal.dm +++ b/code/modules/organs/internal/_internal.dm @@ -44,9 +44,24 @@ if((status & ORGAN_DEAD) && dead_icon) icon_state = dead_icon -/obj/item/organ/internal/proc/surgical_fix() //to be used for scarring -mattatlas +/obj/item/organ/internal/proc/surgical_fix(mob/user) + if(damage > min_broken_damage) + var/scarring = damage/max_damage + scarring = 1 - 0.3 * scarring ** 2 // Between ~15 and 30 percent loss + var/new_max_dam = Floor(scarring * max_damage) + if(new_max_dam < max_damage) + to_chat(user, "Not every part of [src] could be saved, some dead tissue had to be removed, making it more suspectable to damage in the future.") + set_max_damage(new_max_dam) heal_damage(damage) +/obj/item/organ/internal/proc/get_scarring_level() + . = (initial(max_damage) - max_damage)/initial(max_damage) + +/obj/item/organ/internal/proc/get_scarring_results() + var/scar_level = get_scarring_level() + if(scar_level > 0.01) + . += "[get_wound_severity(get_scarring_level())] scarring" + /obj/item/organ/internal/is_usable() return ..() && !is_broken() diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index e0c67a9841d..6fee4a9dfce 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -28,6 +28,57 @@ var/healed_threshold = 1 var/oxygen_reserve = 6 +/obj/item/organ/internal/brain/Initialize(mapload) + . = ..() + if(species) + set_max_damage(species.total_health) + else + set_max_damage(200) + if(!mapload) + addtimer(CALLBACK(src, .proc/clear_screen), 5) + +/obj/item/organ/internal/brain/Destroy() + if(brainmob) + qdel(brainmob) + brainmob = null + return ..() + +/obj/item/organ/internal/brain/removed(var/mob/living/user) + + for(var/X in traumas) + var/datum/brain_trauma/BT = X + BT.on_lose(TRUE) + BT.owner = null + + var/mob/living/simple_animal/borer/borer = owner.has_brain_worms() + + if(borer) + borer.detatch() //Should remove borer if the brain is removed - RR + + var/obj/item/organ/internal/brain/B = src + if(istype(B) && istype(owner)) + B.transfer_identity(owner) + + ..() + +/obj/item/organ/internal/brain/replaced(var/mob/living/target) + + if(target.key) + target.ghostize() + + if(brainmob) + if(brainmob.mind) + brainmob.mind.transfer_to(target) + else + target.key = brainmob.key + + for(var/X in traumas) + var/datum/brain_trauma/BT = X + BT.owner = owner + BT.on_gain() + + ..() + /obj/item/organ/internal/brain/can_recover() return ~status & ORGAN_DEAD @@ -41,15 +92,6 @@ ..() damage_threshold_value = round(max_damage / damage_threshold_count) -/obj/item/organ/internal/brain/Initialize(mapload) - . = ..() - if(species) - set_max_damage(species.total_health) - else - set_max_damage(200) - if(!mapload) - addtimer(CALLBACK(src, .proc/clear_screen), 5) - /obj/item/organ/internal/brain/process() if(owner) if(damage > max_damage / 2 && healed_threshold) @@ -157,4 +199,108 @@ if(is_broken()) if(!owner.lying) to_chat(owner, "You black out!") - owner.Paralyse(10) \ No newline at end of file + owner.Paralyse(10) + +/obj/item/organ/internal/brain/surgical_fix(mob/user) + var/blood_volume = owner.get_blood_oxygenation() + if(blood_volume < BLOOD_VOLUME_SURVIVE) + to_chat(user, "Parts of [src] didn't survive the procedure due to lack of air supply!") + set_max_damage(Floor(max_damage - 0.25*damage)) + heal_damage(damage) + +/obj/item/organ/internal/brain/get_scarring_level() + . = (species.total_health - max_damage)/species.total_health + +////////////////////////////////////TRAUMAS//////////////////////////////////////// + +/obj/item/organ/internal/brain/proc/has_trauma_type(brain_trauma_type, consider_permanent = FALSE) + for(var/X in traumas) + var/datum/brain_trauma/BT = X + if(istype(BT, brain_trauma_type) && (consider_permanent || !BT.permanent)) + return BT + + +//Add a specific trauma +/obj/item/organ/internal/brain/proc/gain_trauma(datum/brain_trauma/trauma, permanent = FALSE, list/arguments) + var/trauma_type + if(ispath(trauma)) + trauma_type = trauma + traumas += new trauma_type(arglist(list(src, permanent) + arguments)) + else + traumas += trauma + trauma.permanent = permanent + +//Add a random trauma of a certain subtype +/obj/item/organ/internal/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, permanent = FALSE) + var/list/datum/brain_trauma/possible_traumas = list() + for(var/T in subtypesof(brain_trauma_type)) + var/datum/brain_trauma/BT = T + if(initial(BT.can_gain)) + possible_traumas += BT + + var/trauma_type = pick(possible_traumas) + traumas += new trauma_type(src, permanent) + +//Cure a random trauma of a certain subtype +/obj/item/organ/internal/brain/proc/cure_trauma_type(brain_trauma_type, cure_permanent = FALSE) + var/datum/brain_trauma/trauma = has_trauma_type(brain_trauma_type) + if(trauma && (cure_permanent || !trauma.permanent)) + qdel(trauma) + +/obj/item/organ/internal/brain/proc/cure_all_traumas(cure_permanent = FALSE, cure_type = "") + for(var/X in traumas) + var/datum/brain_trauma/trauma = X + if(trauma.cure_type == cure_type || cure_type == CURE_ADMIN) + if(cure_permanent || !trauma.permanent) + qdel(trauma) + if(cure_type != CURE_ADMIN) + break + +//Miscellaneous + +/obj/item/organ/internal/brain/proc/clear_screen() + if (brainmob && brainmob.client) + brainmob.client.screen.Cut() + +/obj/item/organ/internal/brain/proc/transfer_identity(var/mob/living/carbon/H) + brainmob = new(src) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.dna = H.dna.Clone() + brainmob.timeofhostdeath = H.timeofdeath + if(H.mind) + H.mind.transfer_to(brainmob) + + to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a [initial(src.name)].") + callHook("debrain", list(brainmob)) + +/obj/item/organ/internal/brain/examine(mob/user) // -- TLE + ..(user) + if(brainmob && brainmob.client)//if thar be a brain inside... the brain. + to_chat(user, "You can feel the small spark of life still left in this one.") + else + to_chat(user, "This one seems particularly lifeless. Perhaps it will regain some of its luster later..") + +/obj/item/organ/internal/brain/proc/lobotomize(mob/user as mob) + lobotomized = 1 + + if(owner) + to_chat(owner, "As part of your brain is drilled out, you feel your past self, your memories, your very being slip away...") + to_chat(owner, "Your brain has been surgically altered to remove your memory recall. Your ability to recall your former life has been surgically removed from your brain, and while your brain is in this state you remember nothing that ever came before this moment.") + + else if(brainmob) + to_chat(brainmob, "As part of your brain is drilled out, you feel your past self, your memories, your very being slip away...") + to_chat(brainmob, "Your brain has been surgically altered to remove your memory recall. Your ability to recall your former life has been surgically removed from your brain, and while your brain is in this state you remember nothing that ever came before this moment.") + + return + +/obj/item/organ/internal/brain/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W,/obj/item/surgicaldrill)) + if(!can_lobotomize) + return + if(!lobotomized) + user.visible_message("[user] drills [src] deftly with [W] into the brain!") + lobotomize(user) + else + to_chat(user, "The brain has already been operated on!") + ..() \ No newline at end of file diff --git a/code/modules/organs/internal/heart.dm b/code/modules/organs/internal/heart.dm index 66965942984..4811d068d5a 100644 --- a/code/modules/organs/internal/heart.dm +++ b/code/modules/organs/internal/heart.dm @@ -119,7 +119,7 @@ var/blood_volume = round(owner.vessel.get_reagent_amount("blood")) //Blood regeneration if there is some space - if(blood_volume < DEFAULT_BLOOD_SPECIES && blood_volume) + if(blood_volume < species.blood_volume && blood_volume) var/datum/reagent/blood/B = locate() in owner.vessel.reagent_list //Grab some blood if(B) // Make sure there's some blood at all if(weakref && B.data["donor"] != weakref) //If it's not theirs, then we look for theirs - donor is a weakref here, but it should be safe to just directly compare it. diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index a6bb45c2e31..0773e4ef9d0 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -86,6 +86,8 @@ var/atom/movable/applied_pressure //Pressure applied to wounds. It'll make them bleed less, generally. + var/image/hud_damage_image + /obj/item/organ/external/proc/invalidate_marking_cache() cached_markings = null diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 51c5a4e4464..de5238e2c08 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -113,6 +113,7 @@ add_overlay(finished_icon) //So when it's not on your body, it has icons mob_icon.Blend(finished_icon, ICON_OVERLAY) //So when it's on your body, it has icons +/obj/item/organ/external/var/icon_cache_key /obj/item/organ/external/proc/get_icon(var/skeletal) var/gender = "f" @@ -158,18 +159,19 @@ mob_icon.Blend(rgb(s_tone, s_tone, s_tone), ICON_ADD) else mob_icon.Blend(rgb(-s_tone, -s_tone, -s_tone), ICON_SUBTRACT) - + apply_markings() - if(body_hair && hair_color) - var/list/limb_icon_cache = SSicon_cache.body_hair_cache + if(body_hair) + var/list/limb_icon_cache = SSicon_cache.limb_icons_cache var/cache_key = "[body_hair]-[icon_name]-[hair_color]" if(!limb_icon_cache[cache_key]) var/icon/I = icon(species.icobase, "[icon_name]_[body_hair]") I.Blend(hair_color, ICON_ADD) limb_icon_cache[cache_key] = I mob_icon.Blend(limb_icon_cache[cache_key], ICON_OVERLAY) + icon_cache_key = cache_key icon = mob_icon @@ -217,3 +219,37 @@ LAZYADD(cached_markings, genetic_markings) if (LAZYLEN(temporary_markings)) LAZYADD(cached_markings, temporary_markings) + +// Global scope, used in code below. +var/list/flesh_hud_colours = list("#00ff00","#aaff00","#ffff00","#ffaa00","#ff0000","#aa0000","#660000") +var/list/robot_hud_colours = list("#ffffff","#cccccc","#aaaaaa","#888888","#666666","#444444","#222222","#000000") + +/obj/item/organ/external/proc/get_damage_hud_image() + + // Generate the greyscale base icon and cache it for later. + // icon_cache_key is set by any get_icon() calls that are made. + // This looks convoluted, but it's this way to avoid icon proc calls. + var/list/limb_icon_cache = SSicon_cache.limb_icons_cache + if(!hud_damage_image) + var/cache_key = "dambase-[icon_cache_key]" + if(!icon_cache_key || !limb_icon_cache[cache_key]) + limb_icon_cache[cache_key] = icon(get_icon(), null, SOUTH) + var/image/temp = image(limb_icon_cache[cache_key]) + if(species) + // Calculate the required colour matrix. + var/r = 0.30 * species.health_hud_intensity + var/g = 0.59 * species.health_hud_intensity + var/b = 0.11 * species.health_hud_intensity + temp.color = list(r, r, r, g, g, g, b, b, b) + hud_damage_image = image(null) + hud_damage_image.overlays += temp + + // Calculate the required color index. + var/dam_state = min(1,((brute_dam+burn_dam)/max(1,max_damage))) + var/min_dam_state = min(1,(get_pain()/max(1,max_damage))) + if(min_dam_state && dam_state < min_dam_state) + dam_state = min_dam_state + // Apply colour and return product. + var/list/hud_colours = !BP_IS_ROBOTIC(src) ? flesh_hud_colours : robot_hud_colours + hud_damage_image.color = hud_colours[max(1,min(Ceiling(dam_state*hud_colours.len),hud_colours.len))] + return hud_damage_image \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 305d9510161..8720996cb67 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -747,7 +747,7 @@ if (caffeine) if(!modifier) modifier = M.add_modifier(/datum/modifier/stimulant, MODIFIER_REAGENT, src, _strength = caffeine, override = MODIFIER_OVERRIDE_STRENGTHEN) - M.add_chemical_effect(CE_PULSE, caffeine*2) + M.add_chemical_effect(CE_PULSE, 1) M.dizziness = max(0, M.dizziness + adj_dizzy) M.drowsyness = max(0, M.drowsyness + adj_drowsy) M.sleeping = max(0, M.sleeping + adj_sleepy) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 0d0b5e3c75b..831feed0122 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -70,7 +70,7 @@ if(I && I.damage > 0 && !BP_IS_ROBOTIC(I)) user.visible_message("[user] treats damage to [target]'s [I.name] with [tool_name].", \ "You treat damage to [target]'s [I.name] with [tool_name]." ) - I.surgical_fix() + I.surgical_fix(user) var/obj/item/organ/internal/brain/sponge = target.internal_organs_by_name[BP_BRAIN] if(sponge && istype(I, sponge)) target.cure_all_traumas(cure_type = CURE_SURGERY) diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 1af34385dc6..dba665f66b8 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -21,7 +21,7 @@ return 0 var/obj/item/organ/external/affected = target.get_organ(target_zone) - if(!affected) + if(!affected) return return affected.open >= 2 && (affected.status & ORGAN_ARTERY_CUT) @@ -40,7 +40,7 @@ affected.status &= ~ORGAN_ARTERY_CUT affected.update_damages() - if(ishuman(user) && prob(40)) + if(ishuman(user) && prob(40)) user:bloody_hands(target, 0) /datum/surgery_step/fix_vein/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) @@ -103,8 +103,6 @@ user.visible_message("[user] has cut away necrotic tissue from [target]'s [organ_to_fix.name] with \the [tool].", \ "You have cut away necrotic tissue in [target]'s [organ_to_fix.name] with \the [tool].") organ_to_fix.status &= ~ORGAN_DEAD - if(organ_to_fix.max_damage > 15) - organ_to_fix.max_damage -= rand(1, 10) //remove some max damage, since we cut away the organ /datum/surgery_step/fix_dead_tissue/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) diff --git a/html/changelogs/mattatlas-goodcodequestionmarjk.yml b/html/changelogs/mattatlas-goodcodequestionmarjk.yml new file mode 100644 index 00000000000..9a60b99ba4d --- /dev/null +++ b/html/changelogs/mattatlas-goodcodequestionmarjk.yml @@ -0,0 +1,42 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: MattAtlas + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a fancy new health doll." + - rscadd: "Organ scarring now shows on scanners." diff --git a/icons/mob/screen1_health.dmi b/icons/mob/screen1_health.dmi new file mode 100644 index 0000000000000000000000000000000000000000..9cd7a4134202f9dcc7e59246b0a28d934b98b065 GIT binary patch literal 888 zcmV-;1Bd*HP)R~i!&v&s2C_@$iq;xl$;n7f%qhvhuFnvmG^w;GFEcM4yE;>Z z`Gz`B$fc~{>gNIu0sul{N_JQZhUNeO0!>LoK~z|U?N>2U!!Qs$W}uLr0;fuyCxj1B zFw`{6@PgzANuAE6T1=xhcH=gt;Q=)6c??z@jBXt)Das53lPxl{k#Ds*o$ef>|BQ(L zr*)d7lVp-UxC$&a7V}PEqOndr1hfNFKs)dg00*hBgV3L_XdNuS1lFyCiK{^HF`jY8 z87AZ@1B5MDKs<80h9qT1NYUe)K?Rvnr3|is6LLgWP+S^3SBwh@>pkSK8kNKAJ)pde z{{T$9XC;X5G>i5_@%5qD-RFjX8L^1QjT|hs=IP4h&nB0!eOTI-cnOiaWmHTogowxlW^`ZomW>BA~rP9MxQ)Aa-VYM`31cYZnk~(}pus z71jjiprj}_*Bh>Y7u*7zg5DIWpvM*cF`Trcy69Ohval-PMbmeQ1wn20AaWica=xC$ zWWlS2Lml-Ia|fCW;8tME!Ye9l^9@@!^5MxsCu{AFu#W2^;9LEW(<8!h-b=5a)wDb| zcpAa1`tj)l@x5}ululiz1)e&eq%PPJ&sgPqzbiO`SKkhS^S<2W)elO6sb4APUqx_R4t%pG z8Sx0|aglb&V%X9;z7ZJUevym-!TI3-i9^77k8iV9R3K1