feat(anim): Phase L.1c classify combat animation commands

This commit is contained in:
Erik 2026-04-28 11:37:49 +02:00
parent 268af82e28
commit 831392a7b2
3 changed files with 420 additions and 0 deletions

View file

@ -0,0 +1,68 @@
# Combat Animation Planner Pseudocode
## Sources
- Retail `ClientCombatSystem::ExecuteAttack` (`0x0056BB70`): sends
targeted melee or missile attack intent and records pending response state.
It does not choose a local swing animation.
- Retail `ClientCombatSystem::HandleCommenceAttackEvent` (`0x0056AD20`):
starts/updates power-bar and busy UI state. The event carries no
`MotionCommand`.
- Retail command-name table around `0x00803F34`: combat commands include
`Twitch1..4`, `StaggerBackward`, `StaggerForward`, `ThrustMed`,
`SlashHigh`, `Shoot`, `AttackHigh1`, and later offhand/multistrike
commands.
- ACE `Player_Melee.DoSwingMotion` and `GetSwingAnimation`: server chooses
a swing from `CombatManeuverTable.GetMotion(...)` and broadcasts the
selected `MotionCommand` with `UpdateMotion`.
- ACE `CombatManeuverTable.GetMotion`: indexes `(stance, attack height,
attack type)` to one or more motion commands; power level chooses between
multiple entries.
## Retail Rule
Combat GameEvents are state/UI notifications. Motion state is the animation
authority.
## Pseudocode
```text
PlanForEvent(event):
return None
PlanFromWireCommand(wireCommand, speed):
fullCommand = MotionCommandResolver.ReconstructFullCommand(wireCommand)
return PlanFromFullCommand(fullCommand, speed)
PlanFromFullCommand(fullCommand, speed):
kind = ClassifyMotionCommand(fullCommand)
if kind is None:
return None
routeKind = AnimationCommandRouter.Classify(fullCommand)
return Plan(kind, routeKind, fullCommand, speed)
ClassifyMotionCommand(fullCommand):
if command is a combat stance:
return CombatStance
if command is a thrust/slash/backhand/offhand/multistrike motion:
return MeleeSwing
if command is Shoot, MissileAttack*, or Reload:
return MissileAttack
if command is AttackHigh/Med/Low 1..6:
return CreatureAttack
if command is CastSpell, UseMagicStaff, or UseMagicWand:
return SpellCast
if command is Twitch*, Stagger*, FallDown, or Sanctuary:
return HitReaction
if command is Dead:
return Death
return None
```
## Implementation Note
The next table-driven layer can use `DatReaderWriter.DBObjs.CombatTable`
and `DatReaderWriter.Types.CombatManeuver` directly. acdream already
references `Chorizite.DatReaderWriter`; the missing live-state piece is a
named `CombatTable` data-id on player/creature state.