🗺️ Health — Mental Model¶
This page is a map, not API reference.
It answers one question:
Where does my code plug in, and what layer does what?
If you understand this page, you’ll know:
- where damage/heal logic belongs
- what is allowed to mutate state (and what must not)
- how to extend Health without touching HealthSystem
🧩 The Big Idea¶
Health is a pipeline:
- Inputs enter as data (
DamageContext,HealContext) - Rules shape that data (PRE) and react to outcomes (POST)
- Shields intercept damage before HP changes
- HealthSystem is the only owner of HP state and mutation
- Handlers add optional gameplay behaviour around that core
- UI / Debug reads interfaces and visualises state
🔄 Mental Model Diagram¶
Gameplay intent
│
├─► Build context (DamageContext / HealContext)
│
├─► PRE rules (mutate context)
│ - can change numbers
│ - can cancel the attempt
│
├─► Shields (IShield / ShieldChain)
│ - can absorb damage before HP changes
│
├─► HealthSystem (mutates HP)
│ - clamps
│ - raises events
│ - runs death pipeline
│
└─► POST observers
- react to FinalApplied (VFX/SFX/telemetry/reflect/lifesteal)
- must not change the outcome
Healing is the same idea, minus shields:
Heal intent
│
├─► Build HealContext
├─► PRE heal rules (mutate context)
├─► Healing modifiers (IHealingModifier)
├─► HealthSystem.TryHeal (mutates HP)
└─► POST heal observers (SFX/VFX/events/telemetry)
✅ What Mutates vs What Observes¶
| Layer | Can mutate HP? | Can change outcome? | Should contain gameplay logic? |
|---|---|---|---|
Shared types (DamageContext, HealContext) |
✖ | ✖ | ✖ |
PRE rules (IDamageRule, IHealRule) |
✖ | ✔ (by mutating/cancelling) | ✔ (math + gates only) |
Shields (IShield) |
✖ | ✔ (absorb some/all damage) | ✔ (protection behaviour) |
| HealthSystem | ✔ | ✔ | ✖ (no game-specific decisions) |
POST observers (IPostDamageRule, IPostHealRule) |
✖ | ✖ | ✔ (reactions only) |
| Handlers | ✔ (via public APIs) | ✔ (via public APIs) | ✔ (gameplay behaviour) |
| UI / Debug | ✖ | ✖ | ✖ (presentation/testing only) |
🧠 Where To Put Things¶
If you want to…¶
- Prevent damage from applying → PRE damage rule (
IDamageRule) or Authority gate - Apply armor / resist / crit math → PRE damage rule
- Absorb damage with a resource pool → Shield (
IShield) orShieldChain - React to damage (VFX, SFX, telemetry) → POST observer (
IPostDamageRule) - Heal boosts / anti-heal → PRE heal rule (
IHealRule) - Passive “healing received” scaling →
IHealingModifier - Regenerate over time → Handler (
HealthRegenerationHandler) - Temporary invulnerability windows → Handler (
HealthInvincibilityHandler) - Extra life / last stand →
IBeforeDeathHandler(lifecycle seam) - Animator death hooks →
IHealthDeathHandleror a handler that subscribes to events - UI bars / indicators → UI connectors reading
IHealthReadonly
🧷 Extension Points (Supported Seams)¶
Damage¶
- PRE:
IDamageRule(mutate/cancel) - POST:
IPostDamageRule(observe) - Affinities:
IDamageAffinity(victim-side multipliers) - Attacker scaling:
IAttackerDamageModifier - Shields:
IShield, optionalIShieldPreview
Healing¶
- PRE:
IHealRule - POST:
IPostHealRule - Modifiers:
IHealingModifier
Lifecycle¶
- Before death:
IBeforeDeathHandler(can cancel death) - Death pipeline:
IHealthDeathHandler(side effects only) - Authority:
IHealthAuthority(mutation permission)
⚠️ Common Mistakes¶
-
Putting regen in rules
Regen is time-based behaviour → use a handler. -
Mutating health inside rules/observers
Rules should mutate contexts, not HP. Use publicHealthSystemAPIs if you must act. -
Using ShieldPool as a real shield
ShieldPoolis a ticketed accumulator and does not absorb damage. -
Relying on preview as “truth”
Previews are best-effort. Shields withoutIShieldPreviewwill be ignored in preview calculations. -
Assuming multiplayer replication
Authority gates mutation only. Replication is your netcode’s job.
🔗 Next Steps¶
- Start at Using the Health System for setup.
- Use Rules when you need combat math or gates.
- Use Handlers for time-based or gameplay behaviour.
- Use Shields for protection layers.