571. Lesson identity
572. Learning objective
After this lesson, you can produce a damage-flow diagram that assigns ownership to each combat step, identifies the authoritative health transition, and exposes duplicate-authority failures before implementation.
573. Why this matters
An attack is not complete when input is detected or an animation plays. It is complete when a valid combat rule produces an authoritative state transition whose outcome other systems can observe consistently.
A precise damage flow gives you a boundary for implementation and debugging. When an outcome is wrong, you can inspect validation, resolution, state mutation, event publication, and presentation in order instead of searching every weapon, hitbox, animation, and interface script.
574. Prior knowledge
You should already be able to:
- Describe combat as a bounded contract with conditions, authority, and an outcome.
- Separate combat rules from weapon or effect content.
- Identify the attacker, target, proposed damage, and protected neighboring systems in a small encounter.
These capabilities come from the previous lesson, Combat is a contract, not a weapon list.
575. Core concept
A successful attack should follow one authoritative path from intent to outcome:
- Intent requests an attack.
- Validation decides whether the request is allowed.
- Resolution calculates the combat result without mutating target health.
- State ownership applies and records the resolved result as the authoritative health transition.
- Result communication tells observers what state transition occurred.
- Feedback presents that result without recalculating or applying it again.
The ownership distinction is essential:
- The combat resolver owns calculation of the resolved combat result.
- The target health or combat-state owner owns the authoritative health mutation and records the resulting value.
- Presentation, animation, audio, AI, and logging systems may observe the outcome, but they do not acquire health authority by subscribing to an event.
For a successful transition, a DamageResolved event may contain the attacker, target, attack identifier, resolved damage, and resulting health or defeat outcome. It describes a result that the health owner has already applied.
A rejected request follows a separate path. It may emit an AttackRejected event containing the request identity and rejection reason, but it must not emit a successful resolved-damage outcome or cause a health transition.
576. Mental model
Use the single-authority damage chain:
ATTACK INTENT
↓
VALIDATE CONTRACT
↓
RESOLVE DAMAGE ONCE
↓
TARGET HEALTH OWNER APPLIES AND RECORDS THE TRANSITION
↓
EMIT DAMAGE RESOLVED
↓
PRESENT OR OBSERVE THE RESULT
| Stage | Primary question | Authority |
|---|---|---|
| Attack intent | What is being requested? | Attacker or input boundary |
| Contract validation | Is the request legal now? | Combat rule boundary |
| Damage resolution | What result does the rule calculate? | Combat resolver |
| Health transition | Which value changes and is recorded? | Target health or combat-state owner |
| Result event | What successful transition may observers consume? | Combat event publisher |
| Feedback | What should the player see or hear? | Presentation systems |
The invariant is: one valid hit produces one authoritative health transition. Feedback may be repeated or delayed, but health mutation must not be duplicated.
577. Concrete example
Consider a melee attack with these values:
- Attacker:
guard - Target:
courier - Resolved damage:
12 - Target health before the hit:
40 - The attack is in range and the target is not invulnerable
A sound flow is:
Guard requests slash
→ Combat contract validates range and attack state
→ Combat resolver calculates 12 damage without changing health
→ Courier health owner applies and records 40 → 28
→ DamageResolved carries { target: courier, amount: 12, healthAfter: 28 }
→ Hit flash, sound, floating number, combat log, and other observers react
A presentation listener can display 12. It must not subtract another 12. If a hitbox callback also changes health, the courier may end at 16 instead of 28, even though the displayed event data looks correct. That is a duplicate-authority failure.
A rejected attack follows a distinct branch:
Guard requests slash
→ Combat contract rejects the request because the target is out of range
→ No resolution and no health transition occur
→ Optional AttackRejected event communicates the reason
→ Optional feedback presents the rejection
The absence of damage is therefore an explicit result of validation rather than an accidental side effect.
578. Common mistake
A common mistake is treating every listener that receives a hit or result signal as authorized to apply damage. This can happen when a weapon script, hitbox callback, enemy controller, animation event, and interface presenter each contain a subtraction or damage calculation.
The code may appear modular, but its authority is duplicated. Renaming functions does not solve the problem. The correction is to keep calculation in one combat resolver, keep mutation in the target health owner, and make all remaining systems consume the recorded outcome without recalculating or reapplying it.
579. Guided practice
Produce one canonical damage-flow diagram. Add two clearly labelled unauthorized mutation paths to that same diagram: one for Case A and one for Case B. Do not create a separate full diagram for each case.
Use this compact template:
[Attack intent]
↓
[Validation] ── rejected ──→ [AttackRejected] → [Optional rejection feedback]
↓ accepted
[Combat resolver: calculates ______; does not mutate health]
↓ resolved result
[Target health owner: applies and records ______ → ______]
↓
[DamageResolved: carries ____________________]
↓
[Observers and feedback: ____________________]
Unauthorized path A: ____________________ → second health mutation
Unauthorized path B: ____________________ → recalculation + second health mutation
Case A — Hitbox duplicates the health transition
A player attacks a raider with a charged strike. The combat resolver validates the request and calculates 10 damage without changing health. It passes that resolved result to the raider's health owner, which applies and records the authoritative transition from 30 to 20. After observing the result, a hitbox callback performs an unauthorized second subtraction of 10, leaving the raider at 10.
Case B — Presentation recalculates after a valid transition
A player attacks a courier with a quick strike. The combat resolver validates the request and calculates 8 damage. The courier's health owner applies and records the transition from 24 to 16. A floating-number presenter observes DamageResolved, recalculates damage from the attack's base value, and applies another 8 before displaying the number. The courier incorrectly ends at 8.
Complete the diagram and its annotations:
- Write the attack intent in one sentence.
- List the validation conditions and add one rejected branch that produces no health transition.
- Name the combat resolver and state that it calculates the resolved result but does not mutate target health.
- Name the target health owner and state that it applies and records the resolved result.
- Show the resolved-result handoff between those two owners.
- Define the minimum successful
DamageResolvedpayload needed by observers. - Label unauthorized path A with its second system, incorrect
30 → 20 → 10sequence, and correction. - Label unauthorized path B with its second system, incorrect
24 → 16 → 8sequence, and correction.
For each unauthorized path, add three brief notes:
- Cause: Which observer acquired unauthorized mutation authority?
- Evidence: Which value changed twice, and what final value exposes the fault?
- Correction: Which mutation must be removed, and which resolved event data may the observer still consume?
Your diagram must distinguish request, decision, calculation, state mutation, communication, and presentation. A box labelled only “deal damage” is not sufficient evidence.
580. Validation and evidence
Your work is complete when it contains:
- One combat resolver that calculates damage without mutating health.
- One target health owner that applies and records the transition.
- One rejected branch with no damage resolution or health transition.
- One successful
DamageResolvedevent that communicates the applied outcome. - Observers that present or react to the result without changing health.
- Two separately labelled unauthorized paths on the same canonical diagram.
- The intended and incorrect health sequences for both cases.
- A cause, observable evidence, and correction for each duplicate-authority failure.
Review each arrow by asking: Does this step request, decide, calculate, mutate, communicate, or present? If one step performs multiple authority roles, either separate those roles or justify the boundary explicitly.
581. Key takeaways
- Trace combat from intent to outcome instead of beginning with weapon scripts.
- The combat resolver calculates the result; the target health owner applies and records it.
DamageResolvedcommunicates a successful applied outcome, while rejected requests follow a distinct rejection path.- Presentation and other observers must not become additional health authorities.
- Duplicate authority becomes visible when the same health value changes twice for one valid hit.
582. Next lesson
Continue to 2.2 — Enemy AI. Enemy states and transitions may observe DamageResolved or defeat outcomes to decide how to react, but observation does not transfer health authority away from the target health owner.
583. Knowledge check
Answer these items for yourself before reading the answers.
Which system should own the authoritative health transition after a valid hit?
Show answer and feedback
Answer: The target health or combat-state owner
Why: The target health or combat-state owner applies and records the single authoritative transition. Presentation systems only observe the resulting outcome.
What should a successful DamageResolved event primarily communicate?
Show answer and feedback
Answer: The applied outcome, including its relevant target and resolved amount
Why: DamageResolved communicates a successful outcome that the target health owner has already applied. A rejected request should use a distinct rejection path such as AttackRejected.
Which sequence best represents the single-authority damage chain?
Show answer and feedback
Answer: Intent → validation → resolution → target health transition → result event → feedback
Why: This sequence separates the request, decision, calculation, authoritative mutation, communication, and presentation roles.
Which example shows a UI or animation system creating duplicate damage authority?
Show answer and feedback
Answer: An animation event subtracts health after the target health owner has already applied the resolved damage
Why: The target health owner has already applied and recorded the resolved damage. The animation may present that outcome, but subtracting health again creates a second unauthorized transition.