Commit graph

3 commits

Author SHA1 Message Date
Erik
172c6f9aa3 feat(chat): Campaign CH slice CH1 — retail LogTextType color table
Retail colors chat lines by the 34-value wire LogTextType (ACE's
ChatMessageType), NOT by acdream's synthetic 9-value ChatKind. The old
ChatWindowController.RetailChatColor(ChatKind) collapsed distinct retail
colors onto one bucket per ChatKind — e.g. every Channel line rendered
colorLightBlue (Magic's slot) when retail's actual palette spans five
different colors across the Turbine rooms and legacy allegiance family.

Ports ChatInterface::BuildChatColorLookupTable @0x004F31C0 verbatim
(RetailChatColorTable, all 34 RGBA floats read from the PDB-paired
binary's .data section) and threads a new ChatEntry.LogTextType field
through every ingestion site to the correct retail wire value:
HearSpeech/Tell pass the wire chatType through verbatim; Emote/SoulEmote
hard-code 0x0C; the Tell self-echo hard-codes 0x04; legacy ChatChannel
broadcasts derive their type from the channel bit via the new
LegacyChannelChatType helper (ported from the decompiled
Handle_Communication__ChannelBroadcast dispatch, hear vs. own-send);
TurbineChat rooms map through TurbineChatDisplayNames.LogTextType;
CombatChatTranslator's hit/miss/evade lines map to ACE's CombatSelf/
CombatEnemy per Player_Combat.cs; kill/death lines use retail's
decompiled 0x00 Default (not a combat color). ChatWindowController's
transcript now folds LogTextType through RetailChatColorTable with
retail's exact "out-of-range keeps the previous line's color" carry
rule; ChatPanel's combat highlighting sources the same table.

Corrects HearSpeech.cs's doc-comment ChatType legend (4 of 6 entries
were wrong). Adds register row AP-175 for the pre-existing (unchanged)
Popup-renders-in-chat divergence and updates AP-39's stale per-ChatKind
description. Narrows ISSUES #139 — its chat-colors half is done.

Retail renders no chat timestamp prefix path exists in acdream today,
so the "timestamp is always colorGrey 0x0C" rule has nothing to attach
to; noted here per the research doc rather than left silent.

Research: docs/research/2026-08-09-chat-retail-color-table.md
Full Release suite: 11,833 passed / 4 skipped / 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 15:24:09 +02:00
Erik
5276a83087 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>
2026-07-11 21:10:01 +02:00
Erik
3d26c8efde feat(chat): #20 CombatChatTranslator - retail-faithful combat -> ChatLog templates
Subscribes to CombatState's DamageDealtAccepted / DamageTaken /
MissedOutgoing / EvadedIncoming / AttackDone / KillLanded events
and emits chat-line text into ChatLog.OnCombatLine, mirroring
holtburger's templates verbatim from references/holtburger/apps/
holtburger-cli/src/pages/game/panels/chat.rs:221-308.

Pieces:
- ChatLog: new ChatKind.Combat value; new CombatLineKind enum
  (Info / Warning / Error) on ChatEntry; OnCombatLine(text, kind)
  adapter.
- CombatChatTranslator (Core, IDisposable). Static formatters:
  FormatDamageType (slashing/piercing/bludgeoning/fire/cold/acid/
  electric/nether), FormatDamageLocation (head/chest/abdomen/
  upper arm/lower arm/hand/upper leg/lower leg/foot), FormatPercent,
  FormatAttackConditionsSuffix.
- ChatVM.RecentLinesDetailed() returns FormattedLine records with
  kind metadata so panels can render combat lines colored.
- ChatPanel switches on Kind/CombatKind: combat-Info -> yellow,
  combat-Warning -> red incoming-damage, combat-Error -> deep red,
  all others -> existing renderer.Text path.
- GameWindow constructs translator after GameEventWiring.WireAll;
  disposes in OnClosing + live-session failure path.

Templates landed:
  Attacker:  "You hit {def} for {dmg} {dtype} damage ({hp%}). [Crit]{suffix}"
  Defender:  "{atk} hit you for {dmg} {dtype} damage to your {loc} ({hp%})..."
  Evade-out: "{def} evaded your attack."
  Evade-in:  "You evaded {atk}'s attack."
  AttackErr: "Attack sequence finished with {error}."
  Kill:      synthesized "You killed {name}." + server PlayerKilled
             death-message arrives separately via ChatLog.OnPlayerKilled.

Deviations from holtburger templates (documented in source):
- DamageDealt omits Critical-hit suffix until CombatState.DamageDealt
  carries the flag (defender-side has it; attacker-side doesn't yet).
- DamageTaken omits (health%) until CombatState.DamageIncoming
  parses the wire health-percent field.
- AttackConditions suffix is implemented but always empty until the
  bitflag is plumbed into CombatState records.

18 new tests (12 translator + 4 ChatVMCombat + 2 ChatLog).
Solution total: 978 green (243 Core.Net + 639 Core + 96 UI).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 19:55:15 +02:00