⚙️ Health — Rules (Root)¶
This folder is the entry point for the Health rule system.
Rules define how damage and healing behave between incoming data
(DamageContext / HealContext) and the core HealthSystem.
They are the primary extension surface for combat math, modifiers,
and reactive behaviour.
📦 What Rules Are (and Aren’t)¶
Rules are - Declarative behaviour modifiers - Ordered, deterministic pipeline steps - Fully modular and opt-in - Safe to add/remove per-prefab
Rules are not - Core health ownership - Networking or replication logic - UI or presentation systems
Rules sit between input and mutation — nothing more, nothing less.
🧩 What Lives in the Rules Root¶
Priority Definitions¶
DamageRulePriority.csHealRulePriority.cs
These files define the canonical ordering constants used by all rule families.
They live in the Rules root so: - Every rule can reference them - No circular dependencies are introduced - Ordering stays globally consistent
Note
Keep priority constants in the Rules root.
Centralising ordering is what keeps the pipeline deterministic and debuggable.
🔄 Pipeline Overview¶
Damage Pipeline¶
Incoming DamageContext
└─► PRE Damage Rules (ascending Priority)
0–49 Setup / gating
50–149 Crit, Execute, Armor, Affinity
150–199 Attacker / victim multipliers
900 Safety clamps
└─► Shields
Capacity / Rechargeable / Reduction / Chain / Overheal
└─► HealthSystem.ApplyDamage
└─► POST Damage Rules (IPostDamageRule observers)
Reflect, lifesteal, analytics, VFX
Heal Pipeline¶
Incoming HealContext
└─► PRE Heal Rules
Anti-heal, low-HP boosts, custom gates
└─► Healing modifiers (IHealingModifier)
└─► HealthSystem.TryHeal
└─► POST Heal Rules
Events, SFX, VFX, telemetry
PRE rules may: - mutate context values - cancel the operation - short-circuit the chain
POST rules: - observe only - never affect the applied result
🧮 Priority System¶
Every PRE rule declares an integer Priority.
- Lower runs first
- Higher runs later
- POST observers always run after mutation
| Family | File | Range |
|---|---|---|
| Damage | DamageRulePriority.cs |
0–999 |
| Heal | HealRulePriority.cs |
0–999 |
Common Priority Bands (Guidance)¶
| Range | Purpose | Examples |
|---|---|---|
| 0–49 | Setup / gating | TeamRule |
| 50–99 | RNG / crit | CritRule |
| 90–120 | Execute / armor / affinity | ExecuteThresholdRule, ArmorRule, AffinityRule |
| 140–199 | Multipliers | AttackerDamageMultiplierRule, DamageTakenMultiplierRule |
| 900+ | Late clamps & post effects | DamageClampRule, ReflectStacksRule, LifestealRule |
These ranges are conventions, not hard requirements, but following them keeps stacking behaviour predictable.
🗂 Folder Structure¶
| Path | Purpose |
|---|---|
| Abstractions/ | Rule interfaces and deterministic RNG (IAttackerDamageModifier, IRng). |
| Core/ | Context structs and hubs (DamageContext, HealContext, DamageRuleHub, HealRuleHub). |
| DamageRules/ | PRE & POST damage rules (Team, Crit, Armor, Execute, Affinity, Clamp, Reflect, Lifesteal). |
| HealRules/ | PRE & POST heal rules (AntiHeal, LowHPHealBoost, heal events, SFX, VFX). |
| Modifiers/ | Healing modifier seams and helpers (IHealingModifier, HealingUtility) and rule-contributor components (e.g. ReflectBuff). |
| PostEffects/ | POST-damage visual observers (DamageVFXPostRule). |
🚀 Quick Start¶
- Add
DamageRuleHuband/orHealRuleHubto a GameObject withHealthSystem. - Add rule components from:
DamageRules/HealRules/- Assign rule
Priorityusing constants from the Rules root. - Add shields if needed — they run after PRE rules and before mutation.
No rules are required by default.
✍️ Authoring New Rules¶
Damage PRE Rule¶
public class MyRule : MonoBehaviour, IDamageRule
{
public int Priority => DamageRulePriority.Armor + 10;
public bool Apply(ref DamageContext ctx)
{
// mutate RawAmount / Multiplier / FlatDelta
// return false or set ctx.Cancelled to stop the chain
return true;
}
}
Damage POST Rule¶
public class MyObserver : MonoBehaviour, IPostDamageRule
{
public void OnDamageApplied(in DamageContext ctx)
{
if (ctx.FinalApplied <= 0) return;
// VFX, procs, analytics, telemetry
}
}
Heal PRE Rule¶
public class MyHealGate : MonoBehaviour, IHealRule
{
public int Priority => HealRulePriority.AntiHeal + 10;
public bool Apply(ref HealContext ctx)
{
if (/* condition */)
{
ctx.Cancelled = true;
return false;
}
ctx.Multiplier *= 1.25f;
return true;
}
}
❌ What Rules Should Not Do¶
- Do not mutate health directly
- Do not bypass rule hubs
- Do not depend on rule execution order implicitly
- Do not encode networking or authority here
- Do not mix UI or presentation logic into rules
Rules exist to stay small, deterministic, and composable.