Files
VMSolidus e117ef3f87 Nuke Limb Processing (#22814)
<img width="1549" height="857" alt="image"
src="https://github.com/user-attachments/assets/3830233d-0635-4942-b2aa-024651e6cffa"
/>

Limbs make up roughly half of the "Per additional player" processing
overhead, while Organs make up most of the other half.
Not every organ is an easy candidate for "Event-only processing", but
external limbs are significantly easier to do so.

So this PR makes it so that External Limbs no longer require Processing
unless an event happens that would justify them requiring processing.
Which SIGNIFICANTLY reduces the overall additional cost to the
Processing subsystem per player that joins the server.

Oh and I also made the Appendix and Kidneys not require constant
processing. The Appendix will only process if it is hit by an
Appendicitis event, and the Kidneys will only process if they are either
damaged, or you get poisoned.
2026-07-12 20:45:24 +00:00

179 lines
5.9 KiB
Plaintext

/****************************************************
INTERNAL ORGANS DEFINES
****************************************************/
/obj/item/organ/internal
/// Icon to use when the organ has died.
var/dead_icon
/// Modifier for internal organ injury.
var/damage_reduction = 0.5
/// If TRUE, pain messages will point to the parent organ, otherwise it will print the organ name.
var/unknown_pain_location = TRUE
var/toxin_type = "undefined"
/// Used for size calcs.
var/relative_size = 25
/// The icon state to overlay on the mob.
var/on_mob_icon
/// If the icon state has an active overlay.
var/active_overlay = FALSE
/// If the icon state has an active emissive overlay.
var/active_emissive = FALSE
/// Used in character setup.
var/list/possible_modifications = list("Normal","Assisted","Mechanical")
/// The amount all organs heal themselves by per second when not being affected by chems.
var/organ_self_heal_per_second = 0.2
/// Internal organs are frail, man.
min_broken_damage = 10
/obj/item/organ/internal/Destroy()
if(owner && owner.internal_organs)
owner.internal_organs.Remove(src)
owner.internal_organs_by_name[organ_tag] = null
owner.internal_organs_by_name -= organ_tag
while(null in owner.internal_organs)
owner.internal_organs -= null
if(parent_organ in owner.organs_by_name)
var/obj/item/organ/external/E = astype(owner.organs_by_name[parent_organ])
E?.internal_organs -= src
return ..()
/// Sets the internal organ as belonging to the targeted external organ, and matches the target's species/robotness. Also updates all organ lists belonging to the owner.
/obj/item/organ/internal/replaced(mob/living/carbon/human/target, obj/item/organ/external/affected)
. = ..()
// robotic organs emulate behavior of the equivalent flesh organ of the species
if(BP_IS_ROBOTIC(src) || !species)
species = target.species
target.internal_organs |= src
affected.internal_organs |= src
target.internal_organs_by_name[organ_tag] = src
return TRUE
/obj/item/organ/internal/die()
..()
if((status & ORGAN_DEAD) && dead_icon)
icon_state = dead_icon
/obj/item/organ/internal/proc/surgical_fix(mob/user)
if(damage > min_broken_damage)
var/scarring = damage / max_damage
scarring = 1 - 0.5 * scarring ** 2 // Between ~15 and 50 percent loss.
var/new_max_dam = FLOOR(scarring * max_damage, 1)
if(new_max_dam < max_damage)
to_chat(user, SPAN_WARNING("Not every part of [src] could be saved; some dead tissue had to be removed, making it more susceptible to future damage."))
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(), FALSE, FALSE)] scarring"
/obj/item/organ/internal/is_usable()
if(robotize_type)
var/datum/robolimb/R = GLOB.all_robolimbs[robotize_type]
if(!R.malfunctioning_check(owner))
return TRUE
else
return ..() && !is_broken()
/obj/item/organ/internal/proc/is_damaged()
return damage > 0 || special_condition()
/obj/item/organ/internal/proc/special_condition() // For unique conditions
return
/obj/item/organ/internal/robotize(var/company = PROSTHETIC_UNBRANDED)
..()
min_bruised_damage += 5
min_broken_damage += 10
if(company)
model = company
var/datum/robolimb/R = GLOB.all_robolimbs[company]
if(R)
if(robotic_sprite)
icon_state = "[initial(icon_state)]-[R.internal_organ_suffix]"
robotize_type = company
/obj/item/organ/internal/mechassist()
..()
icon_state = "[initial(icon_state)]-assisted"
/obj/item/organ/internal/proc/getToxLoss()
if(BP_IS_ROBOTIC(src))
return damage * 0.5
return damage
/obj/item/organ/internal/proc/set_max_damage(var/ndamage)
max_damage = FLOOR(ndamage, 1)
min_broken_damage = FLOOR(0.75 * max_damage, 1)
min_bruised_damage = FLOOR(0.25 * max_damage, 1)
/obj/item/organ/internal/proc/take_internal_damage(amount, var/silent=0)
START_PROCESSING(SSprocessing, src)
if(BP_IS_ROBOTIC(src))
damage = between(0, src.damage + (amount * 0.8), max_damage)
else
damage = between(0, src.damage + amount, max_damage)
//only show this if the organ is not robotic
if(owner && ORGAN_CAN_FEEL_PAIN(src) && parent_organ && (amount > 5 || prob(10)))
var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
if(parent && !silent)
var/degree = ""
if(is_bruised())
degree = " a lot"
if(damage < 5)
degree = " a bit"
owner.custom_pain("Something inside your [parent.name] hurts[degree]!", amount, affecting = parent)
/obj/item/organ/internal/proc/get_visible_state()
if(damage > max_damage)
. = "bits and pieces of a destroyed "
else if(is_broken())
. = "broken "
else if(is_bruised())
. = "badly damaged "
else if(damage > 5)
. = "damaged "
if(status & ORGAN_DEAD)
if(can_recover())
. = "necrotic and debridable [.]"
else
. = "necrotic and dead [.]"
. = "[.][name]"
/obj/item/organ/internal/process(seconds_per_tick)
..()
if(!owner)
return
if(owner.stasis_value > 0)
// Putting a body in stasis will simultaneously slow down the rate at which organs die
// while also slowing down the rate at which they are healed.
seconds_per_tick /= owner.stasis_value
if(toxin_type in owner.chem_effects)
take_damage(owner.chem_effects[toxin_type] * seconds_per_tick)
handle_regeneration(seconds_per_tick)
tick_surge_damage(seconds_per_tick) //Yes, this is intentional.
/obj/item/organ/internal/proc/handle_regeneration(seconds_per_tick)
SHOULD_CALL_PARENT(TRUE)
if(!damage || BP_IS_ROBOTIC(src) || !istype(owner) || owner.is_asystole() || (owner.chem_effects[CE_TOXIN] || (toxin_type in owner.chem_effects)))
return FALSE
var/repair_modifier = owner.chem_effects[CE_ORGANREPAIR] || organ_self_heal_per_second
if(damage < repair_modifier*max_damage)
heal_damage(repair_modifier * seconds_per_tick)
return TRUE // regeneration is allowed