Skip to content

⚔️ Health — Damage Rules

📦 Folder Overview

This folder contains damage-side rule components that plug into DamageRuleHub.

Damage rules shape incoming damage before it reaches HealthSystem, and define how systems react after damage is applied.

All damage rules are:

  • Modular
  • Order-driven via Priority
  • Authority-agnostic
  • Composable per prefab

🎯 Purpose

Provide a composable, priority-driven pipeline for damage behaviour without modifying core systems.


🧩 What Lives Here

PRE Rules

  • Implement IDamageRule
  • Mutate DamageContext before shields and HP mutation

POST Observers

  • Implement IPostDamageRule
  • Observe finalized results after evaluation

🧠 Usage Guidance

Basic Usage

  1. Add DamageRuleHub to the same GameObject as HealthSystem
  2. Add rule components from this folder
  3. PRE rules run in ascending Priority
  4. POST observers run after evaluation completes (execution for rejected hits is implementation-defined)

No damage rules are required by default.


Common Priority Bands

Priority Purpose Example Rules
40 Team gating TeamRule
50–99 RNG / crit CritRule
90–120 Execute / armor / affinity ExecuteThresholdRule, ArmorRule, AffinityRule
140–199 Multipliers AttackerDamageMultiplierRule, DamageTakenMultiplierRule
900+ Safety & post DamageClampRule, ReflectStacksRule, LifestealRule

See DamageRulePriority.cs for canonical constants.


⚠️ Important Notes

PRE Rule Behaviour

PRE rules may:

  • Modify RawAmount, Multiplier, or FlatDelta
  • Set ctx.Cancelled = true
  • Return false to stop further rule execution

POST Rule Behaviour

POST rules:

  • Do not mutate health state
  • React to finalized results only
  • Use ctx.FinalApplied when damage is applied

Boundaries

Damage rules should not:

  • Modify health directly
  • Assume implicit ordering beyond Priority
  • Embed authority or networking logic
  • Include UI or presentation logic

Rules operate on context and act as extensions, not owners.


🧩 Components

TeamRule (priority 40)

  • Cancels same-team damage unless friendly fire is enabled
  • Applies friendly/enemy scaling
  • Uses DamageContext.TeamId and victim ITeamProvider

CritRule (priority 50)

  • Performs critical hit roll
  • Adds DamageTag.Crit on success
  • Multiplies damage via critMultiplier
  • Supports deterministic or injected RNG

ExecuteThresholdRule (priority 90)

When victim HP% is below threshold:

  • Bypasses shields
  • Bypasses armor rules
  • Marks hit as true damage

ArmorRule (priority 100)

  • Applies flat and percent mitigation
  • Filters by DamageTag
  • Mutates ctx.RawAmount

AffinityRule (priority 120)

  • Queries IDamageAffinity providers
  • Combines multipliers:

  • 0 cancels

  • <1 reduces
  • >1 increases

AttackerDamageMultiplierRule (priority 140)

  • Uses attacker IAttackerDamageModifier
  • Multiplies into ctx.Multiplier

DamageTakenMultiplierRule (priority 150)

  • Victim-side stacked multiplier
  • Supports push/pop/clear
  • Applies clamped product

DamageClampRule (priority 900)

  • Clamps final damage range
  • Prevents extreme or invalid values

ReflectStacksRule (priority 980)

  • Reflects percentage of final applied damage
  • Stack-based accumulation
  • Avoids reflection loops

DamageReflectRule (priority 990)

  • Reflects percentage of final applied damage
  • Tags reflected hits

LifestealRule (priority 999)

  • Heals attacker based on final applied damage
  • Heals attackers through the supported IHealthWriter contract

DamageVFXPostRule

  • Spawns VFX based on damage events
  • Optional scaling and rate limiting

  • Rules Overview
  • Heal Rules
  • Rules Abstractions
  • Modifiers