feat(ui): D.2b item interaction + retail cursors + live character sheet
Lands the codex-worktree D.2b stream plus the extraction the 2026-07-02 UI architecture review mandated before commit: - ItemInteractionController: single owner of double-click use/equip/ container-open, targeted-use mode (health kits), drag-out drop; toolbar shortcut drags don't drop the real item. ItemEquipRules for multi-slot (coat) coverage via equip masks. - Cursor phase: CursorFeedbackController (semantic priority chain: drag > resize > window-move > target-mode > text) + RetailCursorCatalog (enums 0x27/0x28/0x29, hotspot 14,14; ClientUISystem::UpdateCursorState 0x00564630) resolved through the portal EnumIDMap chain by RetailCursorResolver; RetailCursorManager applies dat cursor art to the OS cursor. Register row AP-72 covers the OS standard-cursor fallback. - Character window goes live: CharacterSheetProvider owns sheet assembly, XP-curve/raise-cost math and the raise flow — extracted out of GameWindow per Code Structure Rule 1 instead of committing the ~430-line feature body there. Optimistic XP/credit debits go through eventful store APIs (new ClientObjectTable.UpdateInt64Property + LocalPlayerState.DebitIntProperty/DebitInt64Property) instead of raw property-dictionary writes; register row AP-73 covers the still-missing raise ledger (#163). - RetailWindowFrame: the shared nine-slice window mount recipe; the character window uses it, remaining windows migrate via #164. - Status-bar buttons toggle inventory/character windows; retail row-major backpack ordering; WorldSession.SendUseWithTarget + raise/train sends. GameWindow shrinks 14,214 -> 13,877 lines despite the new features; the sheet/raise logic is unit-tested in CharacterSheetProviderTests instead of trapped in the god object. Build green; full suite 3,286 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e3fc7ac5ba
commit
b7dc91a053
74 changed files with 6669 additions and 238 deletions
|
|
@ -146,6 +146,7 @@ public static class CreateObject
|
|||
// publish it.
|
||||
uint? Useability = null,
|
||||
float? UseRadius = null,
|
||||
uint? TargetType = null,
|
||||
// D.5.1 (2026-06-17): icon overlay/underlay dat ids from the
|
||||
// WeenieHeader optional tail. IconOverlayId is gated by
|
||||
// WeenieHeaderFlag.IconOverlay (0x40000000) in weenieFlags;
|
||||
|
|
@ -645,6 +646,7 @@ public static class CreateObject
|
|||
// SAFE because IconComposer early-returns on id==0 per layer.
|
||||
uint? useability = null;
|
||||
float? useRadius = null;
|
||||
uint? targetType = null;
|
||||
uint iconOverlayId = 0;
|
||||
uint iconUnderlayId = 0;
|
||||
uint uiEffects = 0;
|
||||
|
|
@ -707,7 +709,7 @@ public static class CreateObject
|
|||
if ((weenieFlags & 0x00080000u) != 0) // TargetType u32
|
||||
{
|
||||
if (body.Length - pos < 4) throw new FormatException("trunc TargetType");
|
||||
pos += 4;
|
||||
targetType = ReadU32(body, ref pos);
|
||||
}
|
||||
if ((weenieFlags & 0x00000080u) != 0) // UiEffects u32 ← CAPTURE
|
||||
{
|
||||
|
|
@ -850,7 +852,7 @@ public static class CreateObject
|
|||
physicsState, objectDescriptionFlags,
|
||||
friction, elasticity,
|
||||
IconId: iconId,
|
||||
Useability: useability, UseRadius: useRadius,
|
||||
Useability: useability, UseRadius: useRadius, TargetType: targetType,
|
||||
IconOverlayId: iconOverlayId, IconUnderlayId: iconUnderlayId,
|
||||
UiEffects: uiEffects,
|
||||
WeenieClassId: weenieClassId,
|
||||
|
|
|
|||
|
|
@ -336,11 +336,14 @@ public static class GameEvents
|
|||
|
||||
public static WieldObject? ParseWieldObject(ReadOnlySpan<byte> payload)
|
||||
{
|
||||
if (payload.Length < 12) return null;
|
||||
if (payload.Length < 8) return null;
|
||||
uint wielderGuid = payload.Length >= 12
|
||||
? BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(8))
|
||||
: 0u;
|
||||
return new WieldObject(
|
||||
BinaryPrimitives.ReadUInt32LittleEndian(payload),
|
||||
BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(4)),
|
||||
BinaryPrimitives.ReadUInt32LittleEndian(payload.Slice(8)));
|
||||
wielderGuid);
|
||||
}
|
||||
|
||||
/// <summary>0x0022 InventoryPutObjInContainer: server puts item into container slot.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue