Health System — Integration Surfaces¶
This page explains where new gameplay logic should integrate with the RevFramework Health system.
Adding a new mechanic? Start here
Each gameplay behaviour belongs to a specific extension surface. Choosing the correct surface keeps systems predictable, maintainable, and compatible with the rest of the framework.
The Health architecture is intentionally modular.
Extension Surfaces Overview¶
| Goal | Extension Point | Example |
|---|---|---|
| Modify damage calculation | PRE Damage Rule (IDamageRule) | armor, crit, execute |
| Modify healing calculation | PRE Heal Rule (IHealRule) | anti-heal, low HP boost |
| React to finalized damage | POST Damage Rule (IPostDamageRule) | lifesteal, reflect, VFX |
| React to finalized healing | POST Heal Rule (IPostHealRule) | SFX, UI |
| Intercept damage before HP | Shield (IShield) | barrier, temp HP |
| Timed mutation | Effects (DotEffect, HotEffect) | poison DOT, regen HOT |
| Block mutation entirely | Authority (IHealthAuthority) | server authority |
| Extend lifecycle behavior | Handlers (IBeforeDeathHandler, IHealthDeathHandler) | extra lives, revive logic, death effects |
| Direct HP mutation | HealthSystem APIs (IHealthWriter, lifecycle APIs) | setup, persistence, debugging |
| Read health state | IHealthReadonly | UI, AI checks |
Example Decision Flow¶
Critical Hits¶
Use:
IDamageRule
Critical hits modify the damage calculation, so they belong in the PRE rule pipeline.
Fire Damage Over Time¶
Use:
DotEffect
DOT is time-based mutation, which is exactly what Effects are designed for.
Temporary Barrier / Temporary HP¶
Use:
CapacityShield
RechargeableShield
OverhealShield
These intercept damage before it reaches HP or provide temporary HP buffers.
Lifesteal¶
Use:
IPostDamageRule
Lifesteal reacts to final damage applied, not the math before it.
Regeneration¶
Use:
HealthRegenerationHandler
Regen is a companion system that coordinates healing over time.
Multiplayer Authority¶
Use:
IHealthAuthority
Authority determines whether mutation is allowed, not how damage is calculated.
It does not modify damage values or healing behaviour.
UI Health Bars¶
Depend on:
IHealthReadonly
UI should read health state but never mutate it.
Rules vs Shields¶
Rules modify damage calculation.
Shields modify damage interception.
Rules operate before shields.
Shields operate after rules but before health mutation.
| Behaviour | Implementation |
|---|---|
| Resistance | Rule |
| Crit | Rule |
| Execute | Rule |
| Damage cap | Rule |
| Reflect | POST Rule |
| Capacity barrier | Shield |
| Temporary HP | Shield |
Effects vs Rules¶
Effects are time-based gameplay decorators.
Rules are instantaneous calculation modifiers.
Effects apply repeated mutation over time using the same public mutation surfaces (IHealthMutator, IHealthWriter).
| Behaviour | Correct Surface |
|---|---|
| Damage or healing over time | DotEffect / HotEffect — but read the next section first if you also own Status Effects |
| Burn damage scaling | IDamageRule |
| Anti-heal debuff | IHealRule |
Choosing between DotEffect and a status¶
If you own Status Effects as well as Health, you have two ways to build a poison, and they are not interchangeable. Health ships DotEffect / HotEffect; Status Effects ships PoisonStatus and BurnStatus, and the Status ↔ Health integration adds RegenStatus. Both apply damage or healing on a timer through the Health pipeline, so both are subject to rules, shields, invincibility and authority. Everything else about them differs.
DotEffect / HotEffect | PoisonStatus / BurnStatus / RegenStatus | |
|---|---|---|
| Ships with | Health | Status Effects (RegenStatus with the Status ↔ Health integration) |
| Authored as | An inspector component on the target — one per object, requires HealthSystem | A code-constructed instance handed to StatusEffectController.ApplyStatus |
| Magnitude | Whole points per tick, on a fixed interval | Points per second, accumulated and paid out in whole points |
| Stacking | Refresh / Additive / Independent, with maxStacks | Replace, plus controller-level caps (SetStackCap, SetPerSourceStacks) |
| Damage typing | A DamageTag you pick per component | Supplied by the integration's tick route, derived from the status id |
| Attributed to an attacker | ✔ Attacker and team are recorded per stack | ❌ Never — a tick has no live attacker, and inventing one would misreport who dealt it |
| Dispel / cleanse | ❌ Not a concept in Health | ✔ IDispellable, with a dispel type and tier |
| Potency / resistance scaling | ❌ None | ✔ Through IStatusMathService, aura zones, and per-tag resistance |
| Visible to status UI | ❌ | ✔ |
| Timing control | Per component: unscaled time, deterministic jitter, initial offset | Per controller: StatusTimeMode, or a custom ITimeSource |
| Death / revive | clearOnDeath / clearOnRevive per component | Controller teardown |
Which to use¶
Use DotEffect / HotEffect when the effect is a property of the target, when you need it to work with Health alone, when you want per-source independent stacks, or when it matters who applied it — a burning oil trail that credits the kill to the player who lit it needs the attribution that only DotEffect carries.
Use a status when the effect is part of a wider condition system: something the player can cleanse, that a resistance should shorten, that an aura should amplify, or that belongs in a buff bar. That is the whole reason Status Effects exists, and none of it is retrofittable onto DotEffect.
Switching later is a balance change, not a refactor
The two do not compute the same totals. DotEffect deals whole points per tick; a status accumulates a floating-point rate and pays out whole points as they accrue, so the same "5 damage per second for 3 seconds" lands differently at the edges. Tag interaction differs too — a DotEffect carries the DamageTag you chose, while a status is typed from its status id — so resistances and immunities that matched one may not match the other. Decide before you tune, not after.
Common Mistakes¶
Avoid the following
- Mutating
CurrentorMaxdirectly - Calling internal methods instead of public APIs
- Embedding combat logic inside Authority
- Using POST rules to change damage math (POST rules must not mutate core damage calculation)
- Treating
ShieldPoolas an absorbing shield (it does not intercept damage)
Architecture Summary¶
Damage Attempt
↓
Authority Gate
↓
State Guards (Dead / Invincible / Damage Locked)
↓
PRE Rules
↓
Damage Evaluation (raw → multiplier → flat)
↓
Shield Absorption
↓
HP Mutation
↓
POST Observers
↓
Death Interception (IBeforeDeathHandler)
↓
Death Finalization (IHealthDeathHandler + events)
Every extension surface plugs into one of these stages.
Direct Mutation Warning¶
Direct mutation bypasses the pipelines
Direct mutation APIs (e.g. SetCurrent, SetMax, snapshot restore) bypass the standard damage and healing pipelines.
They should only be used for:
- setup
- persistence
- controlled non-combat workflows
Related Docs¶
- Mental Model
- Public API
- System Guarantees Matrix
- FAQ