fix #211: index login-equipped items under player

Project PlayerDescription equipment through the same contained-by-wielder ownership and ordered contents index as live WieldObject updates. Preserve equip masks and priorities so retail GetObjectAtLocation selects Missile for an already-equipped crossbow instead of sending a server-rejected Melee request.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 10:40:29 +02:00
parent e74efc5c06
commit ab98cda26b
6 changed files with 150 additions and 12 deletions

View file

@ -452,6 +452,61 @@ public sealed class GameEventWiringTests
Assert.Equal(1u, items.Get(0x50000A02u)!.ContainerTypeHint);
}
[Fact]
public void PlayerDescription_IndexesLoginEquipmentForDefaultCombatMode()
{
const uint playerGuid = 0x50000001u;
const uint packItemGuid = 0x50000A01u;
const uint crossbowGuid = 0x50000B01u;
var dispatcher = new GameEventDispatcher();
var items = new ClientObjectTable();
GameEventWiring.WireAll(
dispatcher,
items,
new CombatState(),
new Spellbook(),
new ChatLog(),
playerGuid: () => playerGuid);
var sb = new MemoryStream();
using var w = new BinaryWriter(sb);
w.Write(0u); // propertyFlags
w.Write(0x52u); // weenieType
w.Write(0x201u); // ATTRIBUTE | ENCHANTMENT
w.Write(1u); // has_health
w.Write(0u); // attribute_flags
w.Write(0u); // enchantment_mask
w.Write(0u); // option_flags
w.Write(0u); // options1
w.Write(0u); // legacy hotbar count
w.Write(0u); // spellbook_filters
w.Write(1u); // inventory count
w.Write(packItemGuid); w.Write(0u);
w.Write(1u); // equipped count
w.Write(crossbowGuid);
w.Write((uint)EquipMask.MissileWeapon);
w.Write(7u); // layering priority
var envelope = GameEventEnvelope.TryParse(
WrapEnvelope(GameEventType.PlayerDescription, sb.ToArray()));
dispatcher.Dispatch(envelope!.Value);
ClientObject crossbow = items.Get(crossbowGuid)!;
crossbow.Type = ItemType.MissileWeapon;
crossbow.CombatUse = 2;
var orderedPlayerContents = items.GetContents(playerGuid)
.Select(guid => items.Get(guid)!)
.ToList();
Assert.Equal(new[] { packItemGuid, crossbowGuid }, items.GetContents(playerGuid));
Assert.Equal(playerGuid, crossbow.ContainerId);
Assert.Equal(EquipMask.MissileWeapon, crossbow.CurrentlyEquippedLocation);
Assert.Equal(7u, crossbow.Priority);
Assert.Equal(
CombatMode.Missile,
CombatInputPlanner.GetDefaultCombatMode(orderedPlayerContents));
}
[Fact]
public void WireAll_QueryItemManaResponse_RoutesValidityToItemManaState()
{