feat(combat): port retail basic combat bar

Mount authored gmCombatUI, share one press/hold/release request state machine across DAT buttons and keybindings, and recover the exact 1.0s/0.8s power timing from matching retail x86. The same timer fixes jump charge, while ready-stance, response queueing, auto-repeat, layout binding, migration, and conformance coverage keep behavior architectural rather than panel-local.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-11 14:03:28 +02:00
parent 9958458318
commit 2215c76c7e
22 changed files with 1265 additions and 46 deletions

View file

@ -50,6 +50,38 @@ public enum CombatAttackAction
/// </summary>
public static class CombatInputPlanner
{
/// <summary>
/// Retail MotionStance_DualWieldCombat. GetPowerBarLevel (0x0056ADE0)
/// selects the faster 0.8-second charge when this is the current style.
/// </summary>
public const uint DualWieldCombatStyle = 0x80000046u;
public const uint ReadyForwardCommand = 0x41000003u;
public const double AttackPowerUpSeconds = 1.0;
public const double DualWieldPowerUpSeconds = 0.8;
/// <summary>
/// Attack-time branch of retail <c>PlayerInReadyPosition</c>
/// (0x0056B820, arg2=true). Melee accepts a valid maneuver table;
/// every player has one, while missile additionally requires one of
/// retail's launcher/thrown styles to be at Ready.
/// </summary>
public static bool PlayerInReadyPositionForAttack(
CombatMode mode,
uint currentStyle,
uint forwardCommand)
{
if (mode == CombatMode.Melee)
return true;
if (mode != CombatMode.Missile || forwardCommand != ReadyForwardCommand)
return false;
return currentStyle is 0x8000003Fu
or 0x80000041u
or 0x80000043u
or 0x80000047u
or 0x80000138u
or 0x80000139u;
}
private const EquipMask PrimaryWeaponLocations =
EquipMask.MeleeWeapon | EquipMask.MissileWeapon | EquipMask.TwoHanded;