Move limb image updating from life ticks to signals. (#21372)

title,should fix a lot of lag

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
This commit is contained in:
Matt Atlas
2025-10-05 17:23:35 +00:00
committed by GitHub
co-authored by Matt Atlas
parent be42bc0fb4
commit f6037f893a
5 changed files with 170 additions and 79 deletions
+21 -9
View File
@@ -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)
+76 -68
View File
@@ -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()
+12 -2
View File
@@ -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()