fix(combat): match retail live attack feedback

Keep AttackDone control statuses out of chat, preserve dead motion across zero-velocity position updates, render the authored power meter from right to left, and retain the rotatable viewer offset during target tracking.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-11 21:10:01 +02:00
parent 33cc9aa16a
commit 5276a83087
16 changed files with 231 additions and 67 deletions

View file

@ -47,7 +47,6 @@ public sealed class CombatChatTranslator : IDisposable
private readonly Action<CombatState.DamageIncoming> _onTaken;
private readonly Action<string> _onMissed;
private readonly Action<string> _onEvaded;
private readonly Action<uint, uint> _onAttackDone;
private readonly Action<string, uint> _onKill;
private bool _disposed;
@ -61,14 +60,12 @@ public sealed class CombatChatTranslator : IDisposable
_onTaken = HandleDamageTaken;
_onMissed = HandleMissedOutgoing;
_onEvaded = HandleEvadedIncoming;
_onAttackDone = HandleAttackDone;
_onKill = HandleKillLanded;
_combat.DamageDealtAccepted += _onDealt;
_combat.DamageTaken += _onTaken;
_combat.MissedOutgoing += _onMissed;
_combat.EvadedIncoming += _onEvaded;
_combat.AttackDone += _onAttackDone;
_combat.KillLanded += _onKill;
}
@ -80,7 +77,6 @@ public sealed class CombatChatTranslator : IDisposable
_combat.DamageTaken -= _onTaken;
_combat.MissedOutgoing -= _onMissed;
_combat.EvadedIncoming -= _onEvaded;
_combat.AttackDone -= _onAttackDone;
_combat.KillLanded -= _onKill;
}
@ -141,25 +137,6 @@ public sealed class CombatChatTranslator : IDisposable
_chat.OnCombatLine($"You evaded {attackerName}'s attack.", CombatLineKind.Info);
}
private void HandleAttackDone(uint attackSequence, uint weenieError)
{
if (weenieError == 0)
{
// chat.rs:223-228 — silent on a clean finish (debug tag in
// holtburger). We mirror: AttackDone with no error doesn't
// need a chat line; the engine state already advanced.
return;
}
// chat.rs:230-234 — "Attack sequence finished with {:?}.".
// {:?} formats the WeenieError variant name; without that enum
// mapped client-side we surface the hex code (matches the style
// of ChatLog.OnWeenieError).
var line = "Attack sequence finished with WeenieError 0x"
+ weenieError.ToString("X4", CultureInfo.InvariantCulture)
+ ".";
_chat.OnCombatLine(line, CombatLineKind.Error);
}
private void HandleKillLanded(string victimName, uint victimGuid)
{
// chat.rs:301-303 — KillerNotification: "{death_message}".

View file

@ -92,6 +92,8 @@ public static class WeenieErrorMessages
[0x0535] = "You do not have the authority within your allegiance to do that.",
// Movement / teleport / housing
[0x0036] = "Action cancelled!", // ActionCancelled
[0x003D] = "You charged too far!", // YouChargedTooFar
[0x0498] = "You have moved too far!", // YouHaveMovedTooFar
[0x0499] = "That is not a valid destination!", // TeleToInvalidPosition
[0x0532] = "You must wait 30 days after purchasing a house before you may purchase another with any character on the same account.",