fix: worn gear lifted off a corpse stays loot when put back (#2701)

A corpse's worn-gear list was fixed at creation, and clients learn worn gear only from the 0x89 packet sent on first sight. A piece lifted and dropped back showed as loose loot to everyone watching, but came back "worn" after a relog. Lifting now takes the piece off the list, so every view agrees it is loot.

Programmatic moves (the duel gather-and-re-equip in `DuelContext`) don't go through `OnItemLifted` and still see the original list.
This commit is contained in:
Kamron Batman 2026-10-09 17:02:36 -07:00 • committed by GitHub
parent 0dbb0f5a2c
commit 1992c9d1b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 0 deletions

View file

@ -0,0 +1,42 @@
using System.Collections.Generic;
using Server;
using Server.Items;
using Xunit;
namespace UOContent.Tests;
[Collection("Sequential UOContent Tests")]
public class CorpseLootTests
{
[Fact]
public void LiftedWornGear_PutBack_StaysLoot()
{
var owner = new Mobile((Serial)0x1);
owner.DefaultMobileInit();
owner.Body = 0x190;
// Weapons take their layer from tiledata, which CI doesn't load.
var sword = new VikingSword { Layer = Layer.OneHanded };
Assert.True(owner.EquipItem(sword));
var corpse = new Corpse(owner, new List<Item> { sword });
corpse.DropItem(sword);
try
{
Assert.Contains(sword, corpse.EquipItems);
corpse.OnItemLifted(owner, sword);
sword.Internalize();
corpse.DropItem(sword);
Assert.Same(corpse, sword.Parent);
Assert.DoesNotContain(sword, corpse.EquipItems);
}
finally
{
corpse.Delete();
owner.Delete();
}
}
}

View file

@ -812,6 +812,10 @@ public partial class Corpse : Container, ICarvable
AddToLooters(from);
_instancedItems?.Remove(item);
// Lifted gear is loot from then on. Clients only learn worn gear from 0x89 on first sight, so a
// piece put back would show worn after a relog but loose to everyone already watching.
RemoveFromEquipItems(item);
}
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)