from __future__ import annotations from engine.character import Character from engine.defs import DefRegistry def apply_organ_interactions_tick(character: Character, registry: DefRegistry, ticks: int) -> None: """Damaged organs stress the organs they affect (OrganDef.affects_organs), e.g. a weakened heart gradually strains the kidneys. Damage per tick is proportional to both the source organ's own damage fraction and the elapsed ticks. Sources are snapshotted before any damage is applied, so effects don't cascade within the same tick (a heart hit doesn't also immediately hit whatever the newly-damaged kidneys affect, this call). """ if ticks <= 0: return sources: list[tuple[str, float]] = [] for part in character.resolved_body_parts().values(): if part is None: continue for organ in part.organs: if organ.removed: continue organ_def = registry.get_organ_def(organ.organ_def_id) if not organ_def.affects_organs: continue damage_fraction = 1.0 - (organ.integrity / 100.0) if damage_fraction <= 0.0: continue sources.append((organ_def.id, damage_fraction)) for source_id, damage_fraction in sources: source_def = registry.get_organ_def(source_id) for target_organ_id, rate in source_def.affects_organs.items(): _damage_organ(character, target_organ_id, rate * damage_fraction * ticks) def _damage_organ(character: Character, organ_def_id: str, amount: float) -> None: if amount <= 0: return for slot, part in character.resolved_body_parts().items(): if part is None: continue if not any(o.organ_def_id == organ_def_id for o in part.organs): continue override = character.get_or_create_body_part_override(slot) assert override is not None organ = next(o for o in override.organs if o.organ_def_id == organ_def_id) organ.integrity = max(0.0, organ.integrity - amount) if organ.integrity <= 0.0: organ.removed = True return