feat(ui): spellcasting cast-button + character-panel attribute/skill tooltips — gmSpellcastingUI::UpdateCastButtonTooltip @0x004C6A30, AttributeInfoRegion/Attribute2ndInfoRegion/SkillInfoRegion @0x004F1530/0x004F1680/0x004F2140

TS-85 remainder batch (hover/UI overnight round, batch B). Audit found
three of the four listed spellcasting SetTooltip sites (endowment icon,
favorite, submenu) were already correct via UiCatalogSlot's pre-existing
Label-driven GetTooltipText; only the cast button (UiButton, no tooltip
wiring at all) was a real gap. Ports the verified literal states
("Select a spell to cast" / "You have no spells ready to cast" / the
full endowment-item USE-the-%s branch) plus a documented, narrower
fallback (spell name only) for the one sub-branch whose exact wording
sits behind a genuine gmNoticeHandler vtable-slot collision in the
pseudo-C dump rather than the unlabeled-string-pool class the rest of
this batch recovered.

Character panel: new UiClickablePanel.TooltipText seam (same pattern as
UiButton.TooltipText) carries the six hardcoded attribute descriptions
and three pair-shared vitals descriptions (byte-decoded from the retail
string pool) plus skill tooltips composed from the already-DAT-parsed
SkillBase.Description/.Formula — no hand-transcription needed for the
~30+ skill strings. The formula-to-text algorithm itself
(SkillSystem::InqSkillFormula) was recovered by byte-decoding six short
fragments Binary Ninja left completely unlabeled between two
gmSpellcastingUI vtable declarations.

Live-verified against the local ACE server: 34 real skills' composed
tooltips and both reachable cast-button states captured via a temporary
probe (stripped before this commit). Full solution suite green
(14,647 tests, 0 failures) both before and after the probe strip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-17 01:11:22 +02:00
parent c623b57ad3
commit 39c49e140e
8 changed files with 269 additions and 9 deletions

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using AcDream.App.Net;
using AcDream.Core.Items;
using AcDream.Core.Player;
using DatReaderWriter;
@ -382,6 +383,10 @@ public sealed class CharacterSheetProvider
int specializedCost = skillBase?.SpecializedCost ?? 0;
long raiseCost = SkillRaiseCost(xp, advancement, snapshot, 1);
long raise10Cost = SkillRaiseCost(xp, advancement, snapshot, 10);
// TS-85: SkillInfoRegion::GetTooltip (0x004f1fe0) — formula line +
// DAT description, composed once here (matches retail's once-at-
// construction SetTooltip; the row never recomputes it per frame).
string? tooltipText = skillBase is null ? null : RetailSkillFormula.BuildTooltip(skillBase);
// Issue #267: CurrentLevel is the EFFECTIVE (vitae + buff) level —
// retail CACQualities::EnchantSkill (0x005947b0). VitaeModifier
@ -406,7 +411,8 @@ public sealed class CharacterSheetProvider
specializedCost,
raiseCost,
raise10Cost,
values.VitaeModifier));
values.VitaeModifier,
tooltipText));
}
return result;