Refactor Get Pain (#22847)

This PR refactors get_pain() to be essentially performance free.
Previously it was a member of the top 5 most expensive procs.
I had to touch a metric shitton of files to make this happen. Notably
get_pain() was also 1/3rd of the entire processing cost for Mobs - Life
This commit is contained in:
VMSolidus
2026-08-19 22:50:40 +00:00
committed by GitHub
parent db385f9710
commit 40e88e0d2d
35 changed files with 212 additions and 119 deletions
+98 -39
View File
@@ -31,9 +31,23 @@
//Damage variables. Do not modify brute_dam or burn_dam directly. Use take_damage.
///Actual current brute damage
var/brute_dam = 0
VAR_PRIVATE/brute_dam = 0
/// Amount of pain generated per point of brute damage
VAR_PROTECTED/pain_per_brute = 0.7
///Actual current burn damage
var/burn_dam = 0
VAR_PRIVATE/burn_dam = 0
/// Amount of pain generated per point of burn damage
VAR_PROTECTED/pain_per_burn = 0.8
/// Amount of current genetic damage
VAR_PRIVATE/genetic_degradation = 0
/// Amount of pain generated per point of genetic damage
VAR_PROTECTED/pain_per_genetic = 0.5
/// Amount of pain generated by a limb being dislocated
VAR_PROTECTED/pain_per_dislocation = 5
/// Stores whether or not this limb was broken during the last check.
VAR_PRIVATE/was_broken = FALSE
/// Amount of pain generated by a limb being dislocated
VAR_PROTECTED/pain_per_broken = 10
///Ratio of current brute damage to max damage
var/brute_ratio = 0
@@ -47,8 +61,6 @@
var/last_dam = -1
///Amount of current genetic damage
var/genetic_degradation = 0
///How much the limb hurts
VAR_PRIVATE/pain = 0
@@ -148,7 +160,7 @@
var/amputation_point
/// If the joint is dislocated
var/dislocated = FALSE
VAR_PROTECTED/dislocated = FALSE
/// How often wounds should be updated, a higher number means less often
var/wound_update_accuracy = 1
@@ -357,6 +369,7 @@
if(dislocated == -1)
return
add_pain(pain_per_dislocation)
START_PROCESSING(SSprocessing, src)
if(primary)
dislocated = 2
@@ -373,6 +386,7 @@
START_PROCESSING(SSprocessing, src)
dislocated = 0
remove_pain(pain_per_dislocation)
if(children && children.len)
for(var/obj/item/organ/external/child in children)
if(child.dislocated == 1)
@@ -652,6 +666,9 @@ This function completely restores a damaged organ to perfect condition.
perma_injury = 0
brute_dam = 0
burn_dam = 0
genetic_degradation = 0
if (pain)
remove_pain(pain)
germ_level = 0
QDEL_LIST(wounds)
number_wounds = 0
@@ -782,7 +799,7 @@ This function completely restores a damaged organ to perfect condition.
/obj/item/organ/external/proc/need_process()
if(BP_IS_ROBOTIC(src))
return surge_damage
if(get_pain() || status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED|ORGAN_ARTERY_CUT) || brute_dam || burn_dam)
if(LIMB_GET_PAIN(src) || status & (ORGAN_CUT_AWAY|ORGAN_BLEEDING|ORGAN_BROKEN|ORGAN_DESTROYED|ORGAN_SPLINTED|ORGAN_DEAD|ORGAN_MUTATED|ORGAN_ARTERY_CUT) || brute_dam || burn_dam || length(wounds) || was_broken)
return TRUE
if(last_dam != brute_dam + burn_dam) // Process when we are fully healed up.
last_dam = brute_dam + burn_dam
@@ -802,6 +819,13 @@ This function completely restores a damaged organ to perfect condition.
// Process wounds, doing healing etc. Only do this every few ticks to save processing power
if(owner.life_tick % wound_update_accuracy == 0)
update_wounds()
var/broken = is_broken()
if (!was_broken && broken)
was_broken = TRUE
add_pain(pain_per_broken)
else if (was_broken && !broken)
was_broken = FALSE
remove_pain(pain_per_broken)
//Chem traces slowly vanish
if(owner.life_tick % 10 == 0)
@@ -1029,8 +1053,8 @@ Note that amputating the affected organ does in fact remove the infection from t
//Updates brute_damn and burn_damn from wound damages. Updates BLEEDING status.
/obj/item/organ/external/proc/update_damages()
number_wounds = 0
brute_dam = 0
burn_dam = 0
var/new_brute_dam = 0
var/new_burn_dam = 0
var/cut_dam = 0
status &= ~ORGAN_BLEEDING
var/clamped = 0
@@ -1046,9 +1070,9 @@ Note that amputating the affected organ does in fact remove the infection from t
continue
if(W.damage_type == INJURY_TYPE_BURN)
burn_dam += W.damage
new_burn_dam += W.damage
else
brute_dam += W.damage
new_brute_dam += W.damage
if(W.damage_type == INJURY_TYPE_CUT)
cut_dam += W.damage
@@ -1059,6 +1083,18 @@ Note that amputating the affected organ does in fact remove the infection from t
number_wounds += W.amount
var/brute_difference = new_brute_dam - brute_dam
if (brute_difference)
if (brute_difference > 0)
add_brute_damage(brute_difference)
else remove_brute_damage(brute_difference)
var/burn_difference = new_burn_dam - burn_dam
if (burn_difference)
if (burn_difference > 0)
add_burn_damage(burn_difference)
else remove_burn_damage(burn_difference)
//things tend to bleed if they are CUT OPEN
if (open && !clamped && can_bleed)
status |= ORGAN_BLEEDING
@@ -1414,7 +1450,7 @@ Note that amputating the affected organ does in fact remove the infection from t
return FALSE
if(parent && (parent.tendon_status() & TENDON_CUT))
return FALSE
if(get_pain() > pain_disability_threshold)
if(LIMB_GET_PAIN(src) > pain_disability_threshold)
return FALSE
if(brute_ratio >= 100)
return FALSE
@@ -1663,34 +1699,60 @@ Note that amputating the affected organ does in fact remove the infection from t
return tendon.status
// Damage procs
/obj/item/organ/external/proc/get_brute_damage()
return brute_dam
/obj/item/organ/external/proc/add_brute_damage(amount)
if (amount <= 0)
return
/obj/item/organ/external/proc/get_burn_damage()
return burn_dam
brute_dam += amount
add_pain(amount * pain_per_brute)
/obj/item/organ/external/proc/get_genetic_damage()
return BP_IS_ROBOTIC(src) ? 0 : genetic_degradation
/obj/item/organ/external/proc/remove_brute_damage(amount)
if (amount <= 0)
return
brute_dam -= amount
remove_pain(amount * pain_per_brute)
/obj/item/organ/external/proc/add_burn_damage(amount)
if (amount <= 0)
return
burn_dam += amount
add_pain(amount * pain_per_burn)
/obj/item/organ/external/proc/remove_burn_damage(amount)
if (amount <= 0)
return
burn_dam -= amount
remove_pain(amount * pain_per_burn)
/obj/item/organ/external/proc/remove_genetic_damage(amount)
if (amount <= 0)
return
/obj/item/organ/external/proc/remove_genetic_damage(var/amount)
if(BP_IS_ROBOTIC(src) || (species.flags & NO_SCAN))
genetic_degradation = 0
status &= ~ORGAN_MUTATED
return
return FALSE
var/last_gene_dam = genetic_degradation
genetic_degradation = min(100,max(0,genetic_degradation - amount))
if(genetic_degradation <= 30)
if(status & ORGAN_MUTATED)
unmutate()
to_chat(src, SPAN_NOTICE("Your [name] is shaped normally again."))
return -(genetic_degradation - last_gene_dam)
var/difference = genetic_degradation - last_gene_dam
remove_pain(difference * pain_per_genetic)
return -difference
/obj/item/organ/external/proc/add_genetic_damage(amount)
if (amount <= 0)
return
/obj/item/organ/external/proc/add_genetic_damage(var/amount)
if(BP_IS_ROBOTIC(src) || (species.flags & NO_SCAN))
genetic_degradation = 0
status &= ~ORGAN_MUTATED
return
return FALSE
var/last_gene_dam = genetic_degradation
genetic_degradation = min(100,max(0,genetic_degradation + amount))
if(genetic_degradation > 10)
@@ -1699,22 +1761,16 @@ Note that amputating the affected organ does in fact remove the infection from t
if(!(status & ORGAN_MUTATED) && prob(genetic_degradation))
mutate()
to_chat(owner, SPAN_NOTICE("Something is not right with your [name]..."))
return (genetic_degradation - last_gene_dam)
// Pain/halloss
/obj/item/organ/external/proc/get_pain()
var/difference = genetic_degradation - last_gene_dam
add_pain(difference * pain_per_genetic)
return difference
/obj/item/organ/external/proc/remove_pain(amount)
if (amount <= 0)
return
if(!ORGAN_CAN_FEEL_PAIN(src) || BP_IS_ROBOTIC(src))
return 0
. = pain + 0.7 * brute_dam + 0.8 * burn_dam + 0.5 * get_genetic_damage()
if(is_broken())
. += 10
else if(ORGAN_IS_DISLOCATED(src))
. += 5
for(var/obj/item/organ/internal/I as anything in internal_organs)
. += 0.3 * I.getToxLoss()
/obj/item/organ/external/proc/remove_pain(var/amount)
if(!ORGAN_CAN_FEEL_PAIN(src))
pain = 0
return
var/last_pain = pain
@@ -1722,8 +1778,11 @@ Note that amputating the affected organ does in fact remove the infection from t
SEND_SIGNAL(src, COMSIG_UPDATE_LIMB_IMAGE)
return -(pain-last_pain)
/obj/item/organ/external/proc/add_pain(var/amount)
if(!ORGAN_CAN_FEEL_PAIN(src))
/obj/item/organ/external/proc/add_pain(amount)
if (amount <= 0)
return
if(!ORGAN_CAN_FEEL_PAIN(src) || BP_IS_ROBOTIC(src))
pain = 0
return
var/last_pain = pain
+1 -1
View File
@@ -402,7 +402,7 @@ GLOBAL_LIST_INIT(robot_hud_colours, list("#ffffff","#cccccc","#aaaaaa","#888888"
// 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)))
var/min_dam_state = min(1,(LIMB_GET_PAIN(src)/max(1,max_damage)))
if(min_dam_state && dam_state < min_dam_state)
dam_state = min_dam_state
// Apply colour and return product.
+1 -1
View File
@@ -69,7 +69,7 @@
if(maxdam > 50 && prob(maxdam / 5))
to_chat(src, SPAN_WARNING("A bolt of pain shoots through your body, causing your hands to spasm!"))
drop_item()
var/burning = damaged_organ.burn_dam > damaged_organ.brute_dam
var/burning = LIMB_GET_BURN_DAMAGE(damaged_organ) > LIMB_GET_BRUTE_DAMAGE(damaged_organ)
var/msg
switch(maxdam)
if(1 to 10)
+10
View File
@@ -81,6 +81,12 @@
/datum/wound/Destroy()
if(parent_organ)
// Clear any leftover damage from parent limb.
if (damage)
if (damage_type == INJURY_TYPE_BURN)
parent_organ.remove_burn_damage(damage)
else parent_organ.remove_brute_damage(damage)
LAZYREMOVE(parent_organ.wounds, src)
parent_organ = null
LAZYCLEARLIST(embedded_objects)
@@ -183,6 +189,10 @@
var/healed_damage = min(src.damage, amount)
amount -= healed_damage
src.damage -= healed_damage
if (parent_organ)
if (damage_type == INJURY_TYPE_BURN)
parent_organ.remove_burn_damage(healed_damage)
else parent_organ.remove_brute_damage(healed_damage)
while((src.damage / src.amount) < damage_list[current_stage] && current_stage < length(src.desc_list))
current_stage++