📈 Health — Max Health Modifiers¶
📦 Folder Overview¶
This folder contains runtime helpers that modify effective max health for a co-located HealthSystem.
These components provide stackable, reversible max-health adjustments without modifying core systems.
🎯 Purpose¶
Max-health modifiers provide:
- Flat and multiplier-based max-health changes
- Safe stacking of multiple contributors
- Stable recomputation from a baseline value
🧩 What Lives Here¶
MaxHealthModifierStack¶
MonoBehaviour that requires a co-located HealthSystem.
Supports:
- Flat modifiers
- Multiplier modifiers
- Combined flat and multiplier entries
- Baseline rebasing
- Scoped add/remove usage
⚠️ Important Notes¶
Effective Max Calculation¶
Effective max health is computed as:
round(baseline * productOfMultipliers) + sumOfFlats
The result is floored to at least 1.
Multiplier Semantics¶
1.00→ no change1.20→ +20%0.75→ -25%0.00→ collapses multiplier before final floor safeguard
Baseline Model¶
Modifiers are applied relative to a baseline value.
Baseline can be set via:
- Auto capture on awake
CaptureBaselineFromCurrent()SetBaseline(int)RebaseToCurrent()
The baseline is not the current effective max.
This ensures:
- Stable add/remove behaviour
- Order-independent removal
- Safe coexistence of multiple systems
Clamp Modes¶
Modifiers apply results using one of three modes:
Silent
- Updates max health without emitting events
WithEvents
- May trigger damage-style events or death when clamping
ClampNoDeathEvents
- Clamps safely without triggering damage or death events
Runtime API¶
Add modifiers:
int id1 = stack.PushFlat(25);
int id2 = stack.PushPercentMultiplier(1.20f);
int id3 = stack.Push(10, 0.90f);
Remove modifiers:
stack.Remove(id1);
Clear all:
stack.ClearAll();
Reapply:
stack.Reapply();
Scoped Usage¶
using var scope = stack.PushScoped(25, 1.0f, out int id);
- Removes modifier automatically on dispose
- Allocates a small object (avoid in hot paths)
Behaviour¶
- Reapply occurs automatically on state changes
OnEnable()triggers reapply- Baseline is ensured when pushing entries
- No-op if
HealthSystemis missing or component is disabled
Boundaries¶
Do not:
- Treat this as a handler
- Use it as a rules replacement
- Mutate
HealthSystem.Maxalongside it - Treat multipliers as additive percentages
- Use scoped modifiers in hot loops
🧠 Usage Guidance¶
- Use for stat-style max-health changes
- Prefer stack-based operations over direct mutation
- Keep baseline consistent for predictable results
🔗 Related Documentation¶
- Health System
- Rules
- Handlers
- Effects