# Damage Classification & Descriptor System

## Purpose
This document describes the current centralized damage typing pipeline introduced in `Code/Players/Pawn/Damage/*`.

Goals:
- Keep existing `IDamageable` / `IDamageListener` prefab contracts intact.
- Classify damage once into stable canonical cause/kind values.
- Use canonical data for corpse text and future kill feed/log/karma/scoring logic.
- Keep engine-native entry points supportable through a bridge.
- Keep descriptor text deterministic and host-authored for corpse UI consistency.

## Core files and responsibilities
- `Code/Players/Pawn/Damage/DamageInfo.cs`
  - TerrorTown-side damage payload.
  - Includes `Origin` and `Classification` for canonical metadata.
- `Code/Players/Pawn/Damage/DamageInfoBridge.cs`
  - Converts `Sandbox.DamageInfo` into TerrorTown `DamageInfo`.
  - Resolves engine `GameObject` attacker/weapon references to nullable `Component` references.
- `Code/Players/Pawn/Damage/Classification/TttDamageKind.cs`
  - High-level canonical buckets (Ballistic, Explosion, Fire, Fall, etc.).
- `Code/Players/Pawn/Damage/Classification/TttDamageCause.cs`
  - Stable cause IDs (string constants) for UI/logging/gameplay branching.
- `Code/Players/Pawn/Damage/Classification/TttDamageClassification.cs`
  - Result object produced by classifier (rule/cause/kind/category/priority).
- `Code/Players/Pawn/Damage/Classification/TttDamageRule.cs`
  - One data-driven classifier rule (`Predicate` + output).
- `Code/Players/Pawn/Damage/Classification/TttDamageClassifier.cs`
  - Priority-ordered rule engine (`CreateDefault()` contains current rules).
- `Code/Players/Pawn/Damage/Descriptors/TttDamageDescriptor.cs`
  - Human-facing text metadata for canonical causes.
  - Supports weighted, deterministic text variants and DNA policy hooks.
- `Code/Players/Pawn/Damage/Descriptors/TttDamageDescriptorRegistry.cs`
  - Descriptor lookup and context-aware description resolution.
  - Prefers per-object descriptor source components before cause fallback.
- `Code/Players/Pawn/Damage/Descriptors/DamageDescriptorSourceComponent.cs`
  - Base editor-driven component for damage text/DNA overrides.
- `Code/Players/Pawn/Damage/Descriptors/EquippableDamageDescriptorComponent.cs`
  - Descriptor source for weapons/equipment.
- `Code/Players/Pawn/Damage/Descriptors/MapHazardDamageDescriptorComponent.cs`
  - Descriptor source for map hazards/traps.
- `Code/Players/Pawn/Damage/Descriptors/GenericWorldDamageDescriptorComponent.cs`
  - Descriptor source for non-equippable world entities (props/world explosions).
- `Code/Players/Pawn/Damage/Descriptors/TttDamageDescriptorSourceResolver.cs`
  - Resolves best source component with priority:
    - `Equippable > MapHazard > GenericWorld`.
- `Code/Players/Pawn/Damage/Descriptors/TttDamageTextVariant.cs`
  - Optional weighted text variants with context + predicate filters.
- `Code/Players/Pawn/Damage/Descriptors/TttDamageEvent.cs`
  - Canonical event snapshot used for descriptor context, headshots, and future killfeed/stats/log consumers.
- `Code/Players/Pawn/Damage/Descriptors/TttDamageDescriptorContext.cs`
  - Rendering context enum (`BodyInfo`, `KillFeed`, `ConsoleLog`, `RoundSummary`, `Stats`, `DetectiveInfo`).
- `Code/Players/Pawn/Damage/Classification/DamageCatalog.cs`
  - Central entry point exposing classifier + descriptor registry + origin/headshot/event helpers.
- `Code/Players/Pawn/Damage/DamageInfoExtensions.cs`
  - Tag helper methods used by classifier and integration code.
- `Code/Players/Pawn/Damage/Services/DamageSnapshotService.cs`
  - Host-side authoring of synced last-damage snapshots written into `TerrorTownState`.

## Runtime data flow
1. Damage is produced (bullet/melee/explosion/fire/fall/prop).
2. Producer builds `TerrorTown.DamageInfo` (or bridge converts from `Sandbox.DamageInfo`).
3. `HealthComponent` only reconstructs canonical `DamageInfo` + classification when:
   - a player is involved (victim/attacker/inflictor), or
   - debug convars require canonical dumps.
4. Host builds `TttDamageEvent` and writes `TerrorTownState` snapshot only for lethal player hits (death/corpse UX path).
5. Descriptor registry resolves descriptor source in order:
   - source component on inflictor/attacker (`Equippable > MapHazard > GenericWorld`)
   - fallback by canonical cause in `TttDamageDescriptorRegistry`.
6. Context-specific text is resolved from that descriptor (currently `BodyInfo` consumed in HUD).
7. UI consumes host-authored canonical fields (`LastDamageCause`, `LastDamageDescriptor`, etc.) instead of ad-hoc tag checks.

Event identity notes:
- Damage snapshots use host-authored per-player `uint` revisions (`LastDamageRevision`) instead of per-hit GUIDs.
- Revisions are monotonic and wrap safely if they overflow; no unbounded event list is retained.

## Current integration points
- Classification + gating in damage authority:
  - `Code/Players/Pawn/Damage/HealthComponent.cs`
- Host-authored canonical snapshot storage:
  - `Code/Players/Pawn/Damage/Services/DamageSnapshotService.cs`
  - `Code/Players/Pawn/TerrorTownState.cs`
- Corpse/death text consumer:
  - `Code/UI/Features/Identity/BodyInfo.razor`

## Producer usage guidelines
- Always set `DamageInfo.Position`.
- Prefer also setting `DamageInfo.Origin` at source time for better directional/context systems.
- Set `DamageInfo.HitboxName` when no live `Hitbox` object exists (RPC/system-generated damage).
- Set `Attacker` when there is a responsible player/controller.
- Set `Inflictor` when there is a concrete weapon/entity source.
- If using descriptor source components, ensure the damage-producing object is referenced as `Inflictor` when possible.
- Add tags that reflect physical source (`bullet`, `melee`, `explosion`, `fire`, `fall`, `prop`, etc.).
- If tags are missing/ambiguous, classifier falls back to `world`/`unknown`.

### Indirect attribution (owner chain / push carry)
- Host-side causal attribution is tracked in:
  - `Code/Game/Systems/RoundEvents/Services/DamageResponsibilityService.cs`
- Default indirect attribution window is `5s` (`t.damage.chain_window`).
- Use when your item can cause delayed or environment-mediated kills.

For a new equipment item:
1. When the item meaningfully influences a physics entity (prop/explosive), register it:
   - `DamageResponsibilityService.GetOrCreate( Scene )?.RegisterEntityInfluence( entityComponent, ownerPlayer, "your_reason", sourceComponent );`
2. When the item meaningfully influences a player without immediate damage (push/impulse), register it:
   - `DamageResponsibilityService.GetOrCreate( Scene )?.RegisterPlayerInfluence( victimPlayer, ownerPlayer, "your_reason", sourceComponent );`
3. If your item explodes later, carry owner identity and pass it through `Explosion.AtPoint(...)` attacker arguments whenever possible.
4. Keep direct `DamageInfo.Attacker`/`Inflictor` populated when available; indirect attribution is a fallback chain, not a replacement.

## Adding a new cause (TTT-specific trap/hazard)
1. Add a new cause constant to `TttDamageCause`.
2. Add a rule in `TttDamageClassifier.CreateDefault()` with suitable priority and predicate.
3. Add descriptor text in `TttDamageDescriptorRegistry.CreateDefault()`.
4. Ensure producer sets tags/attacker/inflictor needed by the new predicate.
5. Validate corpse text and debug logs in-game.

## Headshot rules
- Headshot derivation is centralized in `DamageCatalog.IsHeadshot(...)`.
- Supported causes: `bullet`, `melee`, and `prop`.
- Detection sources (in order):
  - `DamageInfo.HitboxName`
  - `DamageInfo.Hitbox.Bone.Name`
  - hitbox tags
  - damage tags

## Descriptor contexts and variants
- Resolve text with:
  - `DamageCatalog.Descriptors.Describe( damageEvent, context )`
  - `DamageCatalog.Descriptors.Describe( damageEvent, context, damageInfo )` (host path with full source context)
- Backward-compatible corpse helper remains:
  - `DamageCatalog.Descriptors.DescribeCorpse( causeId, weaponName )`
- To add variants:
  - Register `AddVariant(...)` on a `TttDamageDescriptor`.
  - Use predicates for conditions like `e => e.IsHeadshot`.
  - Selection is deterministic from event/context fields.

## DNA policy hook
- Each descriptor can provide DNA behavior:
  - static default via `leavesDnaByDefault`
  - dynamic override via `leavesDnaPredicate`
- Query with:
  - `DamageCatalog.Descriptors.LeavesDna( damageEvent )`
  - `DamageCatalog.Descriptors.LeavesDna( damageEvent, damageInfo )` (host path with source component resolution)
- Current snapshot sync includes `LastDamageLeavesDna` on `TerrorTownState`.

## Component-driven descriptor authoring
- Weapons/equipment:
  - Use `EquippableDamageDescriptorComponent` on the weapon/equipment root.
- Non-equippable world objects:
  - Use `GenericWorldDamageDescriptorComponent` (props, some world explosions).
- Map hazards:
  - Use `MapHazardDamageDescriptorComponent` for trap/trigger hazards.
- By default, no override is applied unless override fields are set on the component.

## Debugging
- `t.db.damage` shows raw damage path logs.
- `t.db.damage_class` shows canonical classification output.
- `t.db.damage_dump` shows full payload + canonical reconstruction + snapshot fields.
- `t.db.damage_chain` logs causal influence writes.
- `t.damage_chain.dump` prints active indirect-attribution records.
- `t.damage_chain.clear` clears active indirect-attribution records.
- `t.damage.chain_refresh_interval` controls how often unchanged continuous influences refresh (default `0.25s`).

## Notes
- This is an incremental migration layer. Existing listener interfaces and prefab behavior remain valid.
- Performance guardrails in current path:
  - no per-hit broadcast RPC for damage application.
  - full canonical event construction is skipped for non-player-involved routine damage.
  - host-authored death snapshot is lethal-only for player victims.
- Future cutover target: use canonical cause/kind for kill feed categories, logs, karma/scoring branches, and detective information.
