fix(ui): port exact selected health policy
Replace the toolbar's PWD-bit approximation with retail ObjectIsAttackable composed with the exact player and pet short-circuits. Carry second-header PetOwner through CreateObject, session, and ClientObject state so self, pet, and Free-PK cases match retail while friendly NPCs and attackable non-creatures remain name-only. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
52a80dc531
commit
2644d1d527
18 changed files with 416 additions and 50 deletions
|
|
@ -566,6 +566,29 @@ public sealed class CreateObjectTests
|
|||
Assert.Equal("Pyreal Scarabs", parsed.Value.PluralName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WeenieHeader_secondHeaderPetOwner_isPreservedAfterPrecedingFields()
|
||||
{
|
||||
// PublicWeenieDesc::UnPack @ 0x005AD7AC..0x005AD7F8:
|
||||
// MaterialType, CooldownId, CooldownDuration, then PetOwner.
|
||||
byte[] body = BuildMinimalCreateObjectWithWeenieHeader(
|
||||
guid: 0x50000024u,
|
||||
name: "Combat Pet",
|
||||
itemType: (uint)ItemType.Creature,
|
||||
objectDescriptionFlags: 0x04000000u,
|
||||
weenieFlags: 0x80000000u,
|
||||
weenieFlags2: 0x0000000Eu,
|
||||
materialType: 7u,
|
||||
cooldownId: 11u,
|
||||
cooldownDuration: 12.5,
|
||||
petOwnerId: 0x50000001u);
|
||||
|
||||
var parsed = CreateObject.TryParse(body);
|
||||
|
||||
Assert.NotNull(parsed);
|
||||
Assert.Equal(0x50000001u, parsed.Value.PetOwnerId);
|
||||
}
|
||||
|
||||
private static byte[] BuildMinimalCreateObjectWithWeenieHeader(
|
||||
uint guid,
|
||||
string name,
|
||||
|
|
@ -601,7 +624,11 @@ public sealed class CreateObjectTests
|
|||
byte? radarBlipColor = null,
|
||||
byte? radarBehavior = null,
|
||||
byte? combatUse = null,
|
||||
ushort movementSeq = 0)
|
||||
ushort movementSeq = 0,
|
||||
uint materialType = 0,
|
||||
uint cooldownId = 0,
|
||||
double cooldownDuration = 0,
|
||||
uint petOwnerId = 0)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
WriteU32(bytes, CreateObject.Opcode);
|
||||
|
|
@ -691,6 +718,16 @@ public sealed class CreateObjectTests
|
|||
if ((weenieFlags & 0x10000000u) != 0) WriteU16(bytes, 0); // 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
|
||||
if ((weenieFlags2 & 0x00000002u) != 0) WriteU32(bytes, cooldownId); // CooldownId
|
||||
if ((weenieFlags2 & 0x00000004u) != 0)
|
||||
{
|
||||
Span<byte> tmp = stackalloc byte[8];
|
||||
BinaryPrimitives.WriteDoubleLittleEndian(tmp, cooldownDuration);
|
||||
bytes.AddRange(tmp.ToArray());
|
||||
}
|
||||
if ((weenieFlags2 & 0x00000008u) != 0) WriteU32(bytes, petOwnerId); // PetOwner
|
||||
Align4(bytes);
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue