🧩 Health — Rules Abstractions¶
This folder contains the core rule-level abstractions used by the Health system.
These interfaces define how external systems contribute to damage and healing without coupling themselves to concrete rule implementations.
They are: - Runtime-safe - Netcode-friendly - Deterministic by design - Stable extension seams
If you want to influence combat math without touching HealthSystem or rule code, this is where you plug in.
📦 What These Abstractions Are (and Aren’t)¶
They are - Narrow, single-purpose interfaces - Implemented by gameplay, abilities, buffs, AI, or netcode layers - Consumed by concrete rules inside the Health pipeline
They are not - Rules themselves - State owners - Opinionated gameplay logic
These abstractions exist to keep the rule system open for extension and closed for modification.
⚔️ Attacker-Side Interfaces¶
IAttackerDamageModifier¶
Contributes an attacker-side damage multiplier to the damage pipeline.
Used by:
- AttackerDamageMultiplierRule
public interface IAttackerDamageModifier
{
float GetDamageDealtMultiplier(in DamageContext ctx);
}
Semantics¶
- Implement this on the attacker
- Your value is multiplied into the outgoing damage chain
- Return values:
0→ cancel outgoing damage entirely1→ no change> 1→ amplify damage- Multiple modifiers stack multiplicatively
Typical uses: - Berserk / rage buffs - Temporary power-ups - Weapon enchantments - Ability-driven damage bonuses - AI difficulty scaling
This interface never mutates health directly — it only influences math.
🎲 Deterministic Randomness¶
IRng¶
Minimal RNG abstraction for probabilistic rules.
Used by:
- CritRule
- Any custom rule that requires random rolls
public interface IRng
{
float Next01(); // returns [0,1)
}
This abstraction allows rules to remain: - deterministic when required - replay-safe - multiplayer-authoritative
Built-in RNG Implementations¶
SystemRng¶
- Deterministic and seedable
- Backed by
System.Random - Ideal for:
- authoritative multiplayer
- replays
- lockstep simulations
- automated testing
UnityRng¶
- Uses
UnityEngine.Random.value - Non-deterministic unless Unity’s RNG is manually seeded
- Suitable for:
- single-player games
- cosmetic randomness
- non-critical effects
Example Usage¶
IRng rng = new SystemRng(seed: 1234);
if (rng.Next01() < 0.25f)
{
// 25% chance
}
Because rules depend on IRng rather than UnityEngine.Random,
you can swap randomness sources without changing rule logic.
🧠 Design Notes¶
- These abstractions keep attacker logic separate from victim logic
- They allow abilities, buffs, and AI to influence combat without becoming Health dependencies
- Deterministic RNG is critical for:
- rollback-safe combat
- authoritative servers
- consistent AI simulation
- Safe to implement in any runtime assembly:
- Gameplay
- Abilities
- AI
- Netcode
- Tools
❌ What Not To Do¶
- Do not mutate health inside these interfaces
- Do not embed stateful logic here
- Do not assume execution order beyond the consuming rule
- Do not use these as a replacement for rules
These are contribution points, not behaviour owners.
🔗 See Also¶
- Rules — Core — contexts, hubs, utilities
- Damage Rules — built-in rule catalogue
- CritRule — concrete
IRngusage - Health Abstractions