# Weapons & Damage Authority (Proposal)

## Purpose
This document proposes an authority refactor for weapon state and damage resolution, aligned with the existing lifecycle/spawn authority pattern.

Goals:
- Remove ambiguous RPC ownership for equip/holster/deploy.
- Make damage host-authored and verifiable.
- Keep client responsiveness via local prediction for visuals.
- Preserve existing lifecycle and round-event policy gating.

## Why this refactor
Current behavior has multiple writers for weapon/damage state, which increases race risk:
- Weapon selection/deploy paths are split across inventory, pawn, and weapon RPC entrypoints.
- Weapon switching is not atomic (`holster all` then `deploy target`), which creates transient null/current-missing windows.
- Damage is submitted through broadcast RPC entrypaths, with host mutation checks but weak request validation boundaries.
- Kill, reward, and listener side effects are mixed into health mutation flow, which complicates ordering and debugging.

## Proposed authority map
- Combat orchestration authority: `Code/Game/Combat/CombatSystem.cs`
  - Host-only per-tick coordinator for weapon commands and damage submissions.
- Weapon state authority: `Code/Game/Combat/Services/WeaponStateService.cs`
  - Single writer for current/deployed weapon state and switch sequencing.
- Weapon execution service: `Code/Game/Combat/Services/WeaponExecutionService.cs`
  - Applies host-authoritative deploy/holster/reload transitions atomically.
- Hit validation service: `Code/Game/Combat/Services/HitValidationService.cs`
  - Host ray/traces and anti-desync checks.
- Damage resolution authority: `Code/Game/Combat/Services/DamageResolutionService.cs`
  - Applies hitbox multipliers, armor/modifiers, and policy gating.
- Damage application authority: `Code/Game/Combat/Services/DamageApplicationService.cs`
  - Applies final health/life mutations via `PlayerState` and emits kill events.

Content remains where it belongs:
- Weapon content/config/behaviors: `Code/Items/Weapons/*`
- Pawn health model and local reactions: `Code/Players/Pawn/Damage/*`
- Round policy gating: `Code/Game/Lifecycle/RoundEventPolicy.cs`

## Proposed runtime model

### Weapon switch flow
1. Owner sends `RequestWeaponCommandHost(...)` (owner-only host RPC).
2. `WeaponStateService` validates:
   - ownership,
   - lifecycle state (`PreRound`/`Playing` only),
   - inventory membership,
   - command cooldown/rate.
3. `WeaponExecutionService` applies atomic switch:
   - resolve target,
   - commit new current,
   - reconcile deployed flags in one host transaction.
4. Host replicates `WeaponStateSnapshot` (sequence-numbered) to owner/proxies.
5. Presentation reads snapshot state and renders; no gameplay state writes from presentation.

### Fire/damage flow
1. Owner sends `RequestFireHost(FireCommand)` with shot seed + aim state.
2. Host validates weapon state, fire rate, ammo, lifecycle.
3. `HitValidationService` computes authoritative traces.
4. `DamageResolutionService` computes resolved damage events.
5. `DamageApplicationService` applies health/life changes (host only), triggers kill pipeline, and emits side effects through policy gates.
6. Visual RPCs are broadcast as effects-only (`tracer`, `impact`, `sound`) and never mutate gameplay state.

## RPC contract proposal

### Keep
- Owner -> host command RPCs for intent:
  - `RequestWeaponCommandHost`
  - `RequestFireHost`
- Host -> all/owner effect RPCs for visuals only:
  - muzzle/tracer/impact/sound

### Remove or demote
- Remove gameplay-state mutation from broadcast RPCs:
  - weapon deploy/holster state writes
  - health/damage state writes
- Convert to host-local methods invoked by authority services.

### Sequence and reconciliation
- Every authoritative weapon/fire decision carries `Sequence`.
- Clients ignore stale snapshots and stale effect payloads.
- Optional compact audit logs:
  - `t.db.combat.weapon`
  - `t.db.combat.damage`
  - `t.db.combat.sequence`

## Data contracts (proposed)
- `WeaponCommand`:
  - `PlayerId`, `WeaponId`, `CommandType`, `ClientTick`, `SequenceHint`.
- `WeaponStateSnapshot`:
  - `CurrentWeaponId`, `DeployedWeaponId`, `Sequence`, `ServerTime`.
- `FireCommand`:
  - `WeaponId`, `Origin`, `Direction`, `SpreadSeed`, `ClientTick`, `SequenceHint`.
- `DamageEvent`:
  - `VictimId`, `AttackerId`, `InflictorId`, `Hitbox`, `Tags`, `BaseDamage`, `ResolvedDamage`, `Force`.

## Migration plan

### Phase 1: Weapon single-writer boundary
- Introduce `WeaponStateService` and route all equip/holster paths through it.
- Restrict `Weapon.Deploy/Holster` to host-execution paths only.
- Keep existing visuals; do not change anim graphs yet.

### Phase 2: Damage single-writer boundary
- Add fire intent RPC + host hit validation service.
- Move damage state mutation to host-local application only.
- Retain existing listeners/events, but fed from resolved host events.

### Phase 3: Side-effect cleanup
- Move kill/reward/stat side-effect triggering out of health mutation method into explicit post-resolution event handling.
- Keep `RoundEventPolicy` as the final side-effect gate.

### Phase 4: Presentation and prediction polish
- Local predicted fire FX + sequence reconciliation.
- Remove leftover fallback loops that can mutate weapon selection from render/input edge states.

## Benefits
- Deterministic ownership: one gameplay writer for weapon and damage state.
- Reduced race windows during switch/respawn transitions.
- Better anti-cheat posture and easier host-side auditing.
- Cleaner separation between simulation and presentation.

## Costs / tradeoffs
- More up-front plumbing (commands/snapshots/services).
- Potential short-term complexity during migration when dual paths coexist.
- Requires careful sequencing and compatibility shims to avoid regressions.

## Acceptance criteria
- No gameplay-state writes from broadcast-only effect RPCs.
- No direct state mutation from presentation/viewmodel systems.
- Weapon switch path emits one authoritative state transition per command.
- Damage application is host-only and reproducible from combat logs.
- Existing lifecycle/spawn/round policy docs remain consistent with implementation.

## Related docs
- `Code/Core/Documentation/game-loop.md`
- `Code/Core/Documentation/lifecycle.md`
- `Code/Core/Documentation/spawning.md`
- `Code/Core/Documentation/items-weapons-equipment.md`
- `Code/Core/Documentation/player-pawn.md`
