fix(ui): match retail item appraisal semantics
Preserve PublicWeenieDesc hook identity from CreateObject through the item model so hook appraisals suppress sentinel capacities exactly. Use appraisal-only Value and Burden presence, retain AddItemInfo paragraph and authored font-color selection, and port retail lock, page, enchantment, and spell-block formatting. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
bc47bc4917
commit
d3c5e06fdd
21 changed files with 982 additions and 145 deletions
|
|
@ -559,6 +559,43 @@ public sealed class CreateObjectTests
|
|||
Assert.Equal(7.5f, p.Workmanship);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParse_HookIdentityFields_AreCapturedWithoutMisaligningOverlay()
|
||||
{
|
||||
const uint hookItemTypes = (uint)ItemType.Container;
|
||||
const ushort hookType = 4;
|
||||
byte[] body = BuildMinimalCreateObjectWithWeenieHeader(
|
||||
guid: 0x50000027u,
|
||||
name: "Black Phyntos Hive",
|
||||
itemType: (uint)ItemType.Container,
|
||||
weenieFlags: 0x20000000u | 0x10000000u | 0x40000000u,
|
||||
hookItemTypes: hookItemTypes,
|
||||
hookType: hookType,
|
||||
iconOverlayId: 0x4567u);
|
||||
|
||||
var parsed = CreateObject.TryParse(body);
|
||||
|
||||
Assert.NotNull(parsed);
|
||||
Assert.Equal(hookItemTypes, parsed.Value.HookItemTypes);
|
||||
Assert.Equal((uint)hookType, parsed.Value.HookType);
|
||||
Assert.Equal(0x06004567u, parsed.Value.IconOverlayId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParse_AbsentHookIdentityFields_RemainNull()
|
||||
{
|
||||
byte[] body = BuildMinimalCreateObjectWithWeenieHeader(
|
||||
guid: 0x50000028u,
|
||||
name: "Ordinary Chest",
|
||||
itemType: (uint)ItemType.Container);
|
||||
|
||||
var parsed = CreateObject.TryParse(body);
|
||||
|
||||
Assert.NotNull(parsed);
|
||||
Assert.Null(parsed.Value.HookItemTypes);
|
||||
Assert.Null(parsed.Value.HookType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParse_MovementSequence_SurfacedFromTimestampBlock()
|
||||
{
|
||||
|
|
@ -709,7 +746,9 @@ public sealed class CreateObjectTests
|
|||
uint cooldownId = 0,
|
||||
double cooldownDuration = 0,
|
||||
uint petOwnerId = 0,
|
||||
ushort spellId = 0)
|
||||
ushort spellId = 0,
|
||||
uint hookItemTypes = 0,
|
||||
ushort hookType = 0)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
WriteU32(bytes, CreateObject.Opcode);
|
||||
|
|
@ -809,9 +848,9 @@ public sealed class CreateObjectTests
|
|||
WriteU16(bytes, 0); // count
|
||||
WriteU16(bytes, 768); // numBuckets (retail constant)
|
||||
}
|
||||
if ((weenieFlags & 0x20000000u) != 0) WriteU32(bytes, 0); // HookItemTypes u32
|
||||
if ((weenieFlags & 0x20000000u) != 0) WriteU32(bytes, hookItemTypes); // HookItemTypes u32
|
||||
if ((weenieFlags & 0x00000040u) != 0) WriteU32(bytes, 0); // Monarch u32
|
||||
if ((weenieFlags & 0x10000000u) != 0) WriteU16(bytes, 0); // HookType u16
|
||||
if ((weenieFlags & 0x10000000u) != 0) WriteU16(bytes, hookType); // HookType u16
|
||||
if ((weenieFlags & 0x40000000u) != 0) WritePackedDword(bytes, iconOverlayId); // IconOverlay
|
||||
if ((weenieFlags2 & 0x00000001u) != 0) WritePackedDword(bytes, iconUnderlayId); // IconUnderlay
|
||||
if ((weenieFlags & 0x80000000u) != 0) WriteU32(bytes, materialType); // MaterialType
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue