diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 33098fd66ec..d8fd784b007 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -42,3 +42,6 @@ /// From /mob/living/verb/execute_resist(). Resisting. #define COMSIG_MOB_RESISTED "mob_resist" + +/// From /obj/item/organ/external/take_damage. Updates the limb's colour matrix. Very laggy, so we do it on reaction to stuff. +#define COMSIG_UPDATE_LIMB_IMAGE "update_limb_image" diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 3b600f39801..ecf514fd4cc 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -43,6 +43,8 @@ if(wearing_rig && wearing_rig.offline) wearing_rig = null + var/shock_value = get_shock() + ..() if(life_tick%30==5)//Makes huds update every 10 seconds instead of every 30 seconds @@ -62,14 +64,14 @@ //Random events (vomiting etc) handle_random_events() - handle_shock() + handle_shock(shock_value) handle_pain() handle_fever() //Handles regenerating stamina if we have sufficient air and no oxyloss - handle_stamina() + handle_stamina(shock_value) if (is_diona()) diona_handle_light(DS) @@ -974,7 +976,6 @@ var/image/burning_image = image('icons/mob/screen1_health.dmi', "burning", pixel_x = species.healths_overlay_x) var/midway_point = FIRE_MAX_STACKS / 2 burning_image.color = color_rotation((midway_point - fire_stacks) * 3) - health_images += burning_image // Show a general pain/crit indicator if needed. if(is_asystole()) @@ -1224,7 +1225,11 @@ if(changeling) changeling.regenerate() -/mob/living/carbon/human/proc/handle_shock() +/** + * This proc assumes that if traumatic_shock = null, then a shock value was NOT passed in, and thus it calculates it itself. + * If you for some reason need to call this alongside a lot of other shit that needs shock, make sure you cache that value, because calculating it is expensive. + */ +/mob/living/carbon/human/proc/handle_shock(traumatic_shock = null) if(status_flags & GODMODE) return 0 var/is_asystole = is_asystole() @@ -1241,7 +1246,9 @@ if(is_asystole) shock_stage = max(shock_stage + 1, 61) - var/traumatic_shock = get_shock() + if(isnull(traumatic_shock)) + traumatic_shock = get_shock() + if(traumatic_shock >= max(30, 0.8*shock_stage)) shock_stage += 1 else if (!is_asystole) @@ -1484,15 +1491,20 @@ if((mutations & XRAY)) set_sight(sight|SEE_TURFS|SEE_MOBS|SEE_OBJS) -/mob/living/carbon/human/proc/handle_stamina() +/** + * This proc assumes that if shock_value = null, then a shock value was NOT passed in, and thus it calculates it itself. + * If you for some reason need to call this alongside a lot of other shit that needs shock, make sure you cache that value, because calculating it is expensive. + */ +/mob/living/carbon/human/proc/handle_stamina(traumatic_shock = null) if (species.stamina == -1) //If species stamina is -1, it has special mechanics which will be handled elsewhere return //so quit this function if (!exhaust_threshold) // Also quit if there's no exhaust threshold specified, because division by 0 is amazing. return - var/shock = get_shock() // used again later for stamina regeneration - if (failed_last_breath || (getOxyLoss() + shock) > exhaust_threshold)//Can't catch our breath if we're suffocating + if(isnull(traumatic_shock)) + traumatic_shock = get_shock() // used again later for stamina regeneration + if (failed_last_breath || (getOxyLoss() + traumatic_shock) > exhaust_threshold)//Can't catch our breath if we're suffocating flash_pain(getOxyLoss()/2) return @@ -1509,7 +1521,7 @@ if (stamina != max_stamina) //Any suffocation damage slows stamina regen. //This includes oxyloss from low blood levels - var/regen = stamina_recovery * (1 - min(((getOxyLoss()) / exhaust_threshold) + (shock / exhaust_threshold), 1)) + var/regen = stamina_recovery * (1 - min(((getOxyLoss()) / exhaust_threshold) + (traumatic_shock / exhaust_threshold), 1)) if(is_drowsy()) regen *= 0.85 if (regen > 0) diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 41ad661cd01..371ae130874 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -25,31 +25,30 @@ var/damage_state = "00" - //Damage variables. - var/brute_mod = 1 + //Damage variables. Do not modify brute_dam or burn_dam directly. Use take_damage. ///Actual current brute damage var/brute_dam = 0 - - ///Ratio of current brute damage to max damage - var/brute_ratio = 0 - - - var/burn_mod = 1 - ///Actual current burn damage var/burn_dam = 0 + ///Ratio of current brute damage to max damage + var/brute_ratio = 0 ///Ratio of current burn damage to max damage var/burn_ratio = 0 + /// Brute damage modifier. + var/brute_mod = 1 + /// Burn damage modifier. + var/burn_mod = 1 + var/last_dam = -1 ///Amount of current genetic damage var/genetic_degradation = 0 ///How much the limb hurts - var/pain = 0 + VAR_PRIVATE/pain = 0 ///The amount of `pain` at which a limb becomes unusable var/pain_disability_threshold @@ -84,39 +83,39 @@ var/skin_color var/hair_color - ///A `/list` of wounds + /// A `/list` of wounds var/list/datum/wound/wounds = list() - ///A list of implants present in this organ + /// A list of implants present in this organ var/list/implants = list() - ///Cache the number of wounds, which is NOT wounds.len! + /// Cache the number of wounds, which is NOT wounds.len! var/number_wounds = 0 var/perma_injury = 0 - ///The parent organ + /// The parent organ var/obj/item/organ/external/parent - ///A `/list` of organs that have this organ as a parent + /// A `/list` of organs that have this organ as a parent var/list/obj/item/organ/external/children - ///Boolean, if this organ supports childrens, which will be added in `children` + /// Boolean, if this organ supports childrens, which will be added in `children` var/supports_children = TRUE - ///Internal organs of this body part + /// Internal organs of this body part var/list/obj/item/organ/internal/internal_organs = list() - ///The tendon + /// The tendon var/datum/tendon/tendon - ///A path of the type of tendon to create when this organ is created + /// A path of the type of tendon to create when this organ is created var/tendon_path = /datum/tendon - ///Name of the limb's tendon. Achilles heel, etc. + /// Name of the limb's tendon. Achilles heel, etc. var/tendon_name = "tendon" - ///HP value of the limb's tendon + /// HP value of the limb's tendon var/tendon_health = 30 var/list/tendon_msgs = list("tore apart", "ripped away") @@ -127,28 +126,28 @@ var/stage = 0 var/cavity = 0 - ///Boolean, if it was sabotaged (emagged), make it detonate when it fails + /// Boolean, if it was sabotaged (emagged), make it detonate when it fails var/sabotaged = FALSE - ///Needs to be opened with a saw to access the organs + /// Needs to be opened with a saw to access the organs var/encased - ///Descriptive string used in dislocation + /// Descriptive string used in dislocation var/joint = "joint" - ///Name of the artery. Cartoid, etc. + /// Name of the artery. Cartoid, etc. var/artery_name = "artery" - ///Multiplier for bleeding in a limb + /// Multiplier for bleeding in a limb var/arterial_bleed_severity = 0.75 - ///Descriptive string used in amputation + /// Descriptive string used in amputation var/amputation_point - ///If the joint is dislocated + /// If the joint is dislocated var/dislocated = FALSE - ///How often wounds should be updated, a higher number means less often + /// How often wounds should be updated, a higher number means less often var/wound_update_accuracy = 1 var/body_hair var/painted = 0 @@ -156,45 +155,72 @@ /// The amount of bandages on our sprite var/bandage_level = BANDAGE_LEVEL_NONE - ///For special projectile gibbing calculation, dubbed "maiming" + /// For special projectile gibbing calculation, dubbed "maiming" var/maim_bonus = 0 - ///Markings (body_markings) to apply to the icon + /// Markings (body_markings) to apply to the icon var/list/genetic_markings - ///Same as `genetic_markings`, but not preserved when cloning + /// Same as `genetic_markings`, but not preserved when cloning var/list/temporary_markings - ///The `genetic_markings` and `temporary_markings` cached for perf. reasons + /// The `genetic_markings` and `temporary_markings` cached for perf. reasons var/list/cached_markings var/list/image/additional_images - ///Pressure applied to wounds. It'll make them bleed less, generally. + /// Pressure applied to wounds. It'll make them bleed less, generally. var/atom/movable/applied_pressure var/image/hud_damage_image - ///How many augments you can fit inside this limb + /// How many augments you can fit inside this limb var/augment_limit var/obj/item/organ/internal/infect_target_internal //make internal organs become infected one at a time instead of all at once var/obj/item/organ/external/infect_target_external //make child and parent organs become infected one at a time instead of all at once - ///Dionae limb + /// Dionae limb var/mob/living/carbon/alien/diona/nymph var/nymph_child - ///Whether the limb has an emissive icon state associated with it + /// Whether the limb has an emissive icon state associated with it var/is_emissive = FALSE - ///Whether the limb has an active overlay icon state associated with it + /// Whether the limb has an active overlay icon state associated with it var/is_overlay = FALSE - ///Whether the limb is a tesla limb (required for special handling) + /// Whether the limb is a tesla limb (required for special handling) var/is_tesla = FALSE -/obj/item/organ/external/proc/invalidate_marking_cache() - cached_markings = null +/obj/item/organ/external/Initialize(mapload) + if(robotize_type) + robotize(robotize_type) + drop_sound = 'sound/items/drop/prosthetic.ogg' + pickup_sound = 'sound/items/pickup/prosthetic.ogg' + else + //HACK: Make sure non-emissive organs, if swapped to, are not treated as emissive. Robotized organs have their own handling, but we still need to cover the case where it is somehow swapped to an organic limb + is_emissive = initial(is_emissive) + + . = ..(mapload, FALSE) + if(isnull(pain_disability_threshold)) + pain_disability_threshold = (max_damage * 0.75) + if(owner) + replaced(owner) + sync_colour_to_human(owner) + + if ((status & ORGAN_PLANT)) + limb_flags &= ~ORGAN_CAN_BREAK + + get_icon() + + RegisterSignal(src, COMSIG_UPDATE_LIMB_IMAGE, PROC_REF(modify_damage_hud_image_color)) + + get_damage_hud_image(TRUE) + + if((limb_flags & ORGAN_HAS_TENDON) && !BP_IS_ROBOTIC(src) && tendon_path) + tendon = new tendon_path(src, tendon_name, tendon_health, tendon_msgs) + else if(limb_flags & ORGAN_HAS_TENDON) + limb_flags &= ~ORGAN_HAS_TENDON /obj/item/organ/external/Destroy() if(parent?.children) @@ -235,6 +261,8 @@ . = ..() +/obj/item/organ/external/proc/invalidate_marking_cache() + cached_markings = null /obj/item/organ/external/attack_self(var/mob/user) if(!contents.len) @@ -322,32 +350,6 @@ damage = min(max_damage, (brute_dam + burn_dam)) return -/obj/item/organ/external/Initialize(mapload) - if(robotize_type) - robotize(robotize_type) - drop_sound = 'sound/items/drop/prosthetic.ogg' - pickup_sound = 'sound/items/pickup/prosthetic.ogg' - else - //HACK: Make sure non-emissive organs, if swapped to, are not treated as emissive. Robotized organs have their own handling, but we still need to cover the case where it is somehow swapped to an organic limb - is_emissive = initial(is_emissive) - - . = ..(mapload, FALSE) - if(isnull(pain_disability_threshold)) - pain_disability_threshold = (max_damage * 0.75) - if(owner) - replaced(owner) - sync_colour_to_human(owner) - - if ((status & ORGAN_PLANT)) - limb_flags &= ~ORGAN_CAN_BREAK - - get_icon() - - if((limb_flags & ORGAN_HAS_TENDON) && !BP_IS_ROBOTIC(src) && tendon_path) - tendon = new tendon_path(src, tendon_name, tendon_health, tendon_msgs) - else if(limb_flags & ORGAN_HAS_TENDON) - limb_flags &= ~ORGAN_HAS_TENDON - /obj/item/organ/external/replaced(var/mob/living/carbon/human/target) ..() @@ -572,6 +574,9 @@ //Sync the organ's damage with its wounds update_damages() + + SEND_SIGNAL(src, COMSIG_UPDATE_LIMB_IMAGE) + owner.updatehealth() return update_icon() @@ -937,7 +942,7 @@ Note that amputating the affected organ does in fact remove the infection from t // let the GC handle the deletion of the wound if (W.damage > 0) - updatehud = 1//If there are any wounds with damage to heal, then we'll update health huds + updatehud = TRUE //If there are any wounds with damage to heal, then we'll update health huds // slow healing var/heal_amt = 0 @@ -963,10 +968,12 @@ Note that amputating the affected organ does in fact remove the infection from t // sync the organ's damage with its wounds src.update_damages() + if (updatehud) owner.hud_updateflag = 1022 if(update_icon()) + SEND_SIGNAL(src, COMSIG_UPDATE_LIMB_IMAGE) owner.UpdateDamageIcon(1) //Updates brute_damn and burn_damn from wound damages. Updates BLEEDING status. @@ -1640,6 +1647,7 @@ Note that amputating the affected organ does in fact remove the infection from t owner.emote("scream") if(amount > 5 && owner) owner.undo_srom_pull() + SEND_SIGNAL(src, COMSIG_UPDATE_LIMB_IMAGE) return pain-last_pain /mob/living/carbon/human/proc/undo_srom_pull() diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index f79699eac7c..ad49a9ec910 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -361,12 +361,13 @@ GLOBAL_LIST_INIT(flesh_hud_colours, list("#00ff00","#aaff00","#ffff00","#ffaa00","#ff0000","#aa0000","#660000")) GLOBAL_LIST_INIT(robot_hud_colours, list("#ffffff","#cccccc","#aaaaaa","#888888","#666666","#444444","#222222","#000000")) -/obj/item/organ/external/proc/get_damage_hud_image() +/obj/item/organ/external/proc/get_damage_hud_image(force_update = FALSE) // 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 + var/has_created_image = FALSE if(!hud_damage_image) var/cache_key = "dambase-[icon_cache_key]" if(!icon_cache_key || !limb_icon_cache[cache_key]) @@ -380,6 +381,16 @@ GLOBAL_LIST_INIT(robot_hud_colours, list("#ffffff","#cccccc","#aaaaaa","#888888" temp.color = list(r, r, r, g, g, g, b, b, b) hud_damage_image = image(null) hud_damage_image.overlays += temp + has_created_image = TRUE + + if(has_created_image || force_update) + modify_damage_hud_image_color() + + return hud_damage_image + +/// Modify the damage colour index of the limb image, ONLY if strictly necessary. +/obj/item/organ/external/proc/modify_damage_hud_image_color() + SIGNAL_HANDLER // Calculate the required color index. var/dam_state = min(1,((brute_dam+burn_dam)/max(1,max_damage))) @@ -389,7 +400,6 @@ GLOBAL_LIST_INIT(robot_hud_colours, list("#ffffff","#cccccc","#aaaaaa","#888888" // Apply colour and return product. var/list/hud_colours = !BP_IS_ROBOTIC(src) ? GLOB.flesh_hud_colours : GLOB.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 /// Returns the possible bandage level the external can have right now, see medical.dm for usage /obj/item/organ/external/proc/possible_bandage_level() diff --git a/html/changelogs/mattatlas-lagkiller.yml b/html/changelogs/mattatlas-lagkiller.yml new file mode 100644 index 00000000000..dc19183aac3 --- /dev/null +++ b/html/changelogs/mattatlas-lagkiller.yml @@ -0,0 +1,58 @@ +################################ +# 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 +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# 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, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - experiment: "Moved limb icon updating to signals. This should reduce lag by a considerable amount."