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
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ public sealed class ObjectTableWiringTests
|
|||
Priority = 0x00000005u,
|
||||
ItemsCapacity = 0,
|
||||
ContainersCapacity = 0,
|
||||
HookItemTypes = (uint)ItemType.Container,
|
||||
HookType = 4u,
|
||||
Structure = 80,
|
||||
MaxStructure = 100,
|
||||
Workmanship = 4.5f,
|
||||
|
|
@ -102,6 +104,8 @@ public sealed class ObjectTableWiringTests
|
|||
// --- capacity ---
|
||||
Assert.Equal(0, d.ItemsCapacity);
|
||||
Assert.Equal(0, d.ContainersCapacity);
|
||||
Assert.Equal((uint)ItemType.Container, d.HookItemTypes);
|
||||
Assert.Equal(4u, d.HookType);
|
||||
|
||||
// --- durability ---
|
||||
Assert.Equal(80, d.Structure);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue