From fc0594f87cf3d7e7f592e870e267ab0c5caa92cd Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sat, 26 Mar 2022 21:33:46 -0700 Subject: [PATCH] fix: Codegens TreasureMapChest (#975) --- .../Items/Containers/TreasureMapChest.cs | 900 ++++++++---------- .../Server.Items.TreasureMapChest.v2.json | 55 ++ 2 files changed, 461 insertions(+), 494 deletions(-) create mode 100644 Projects/UOContent/Migrations/Server.Items.TreasureMapChest.v2.json diff --git a/Projects/UOContent/Items/Containers/TreasureMapChest.cs b/Projects/UOContent/Items/Containers/TreasureMapChest.cs index 1bf908694..8d07ca786 100644 --- a/Projects/UOContent/Items/Containers/TreasureMapChest.cs +++ b/Projects/UOContent/Items/Containers/TreasureMapChest.cs @@ -6,594 +6,506 @@ using Server.Gumps; using Server.Network; using Server.Utilities; -namespace Server.Items +namespace Server.Items; + +[Serializable(2, false)] +public partial class TreasureMapChest : LockableContainer { - public class TreasureMapChest : LockableContainer + [SerializableField(0, setter: "private")] + private List _guardians; + + [SerializableField(1)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private bool _temporary; + + [SerializableField(2)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private Mobile _owner; + + [SerializableField(3)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private int _level; + + [TimerDrift] + [SerializableField(4)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private Timer _expireTimer; + + [DeserializeTimerField(4)] + private void DeserializeExpireTimer(TimeSpan delay) { - private List m_Lifted = new(); - - private Timer m_Timer; - - [Constructible] - public TreasureMapChest(int level) : this(null, level) + if (!_temporary) { + _expireTimer = Timer.DelayCall(delay, Delete); } + } - public TreasureMapChest(Mobile owner, int level, bool temporary = false) : base(0xE40) + [Tidy] + [SerializableField(5, setter: "private")] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private HashSet _lifted; + + [Constructible] + public TreasureMapChest(int level) : this(null, level) + { + } + + public TreasureMapChest(Mobile owner, int level, bool temporary = false) : base(0xE40) + { + _owner = owner; + _level = level; + + _temporary = temporary; + _guardians = new List(); + + _expireTimer = Timer.DelayCall(TimeSpan.FromHours(3.0), Delete); + Fill(this, level); + } + + public override int LabelNumber => 3000541; + + public static Type[] Artifacts { get; } = + { + typeof(CandelabraOfSouls), typeof(GoldBricks), typeof(PhillipsWoodenSteed), + typeof(ArcticDeathDealer), typeof(BlazeOfDeath), typeof(BurglarsBandana), + typeof(CavortingClub), typeof(DreadPirateHat), + typeof(EnchantedTitanLegBone), typeof(GwennosHarp), typeof(IolosLute), + typeof(LunaLance), typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow), + typeof(PolarBearMask), typeof(VioletCourage), typeof(HeartOfTheLion), + typeof(ColdBlood), typeof(AlchemistsBauble) + }; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime DeleteTime => _expireTimer.Next; + + public override bool IsDecoContainer => false; + + private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) + { + var rnd = Utility.Random(15); + + if (Core.SE) { - Owner = owner; - Level = level; - DeleteTime = Core.Now + TimeSpan.FromHours(3.0); - - Temporary = temporary; - Guardians = new List(); - - m_Timer = new DeleteTimer(this, DeleteTime); - m_Timer.Start(); - - Fill(this, level); - } - - public TreasureMapChest(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 3000541; - - public static Type[] Artifacts { get; } = - { - typeof(CandelabraOfSouls), typeof(GoldBricks), typeof(PhillipsWoodenSteed), - typeof(ArcticDeathDealer), typeof(BlazeOfDeath), typeof(BurglarsBandana), - typeof(CavortingClub), typeof(DreadPirateHat), - typeof(EnchantedTitanLegBone), typeof(GwennosHarp), typeof(IolosLute), - typeof(LunaLance), typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow), - typeof(PolarBearMask), typeof(VioletCourage), typeof(HeartOfTheLion), - typeof(ColdBlood), typeof(AlchemistsBauble) - }; - - [CommandProperty(AccessLevel.GameMaster)] - public int Level { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime DeleteTime { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Temporary { get; set; } - - public List Guardians { get; private set; } - - public override bool IsDecoContainer => false; - - private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) - { - var rnd = Utility.Random(15); - - if (Core.SE) + if (rnd < 1) { - if (rnd < 1) - { - attributeCount = Utility.RandomMinMax(3, 5); - min = 50; - max = 100; - } - else if (rnd < 3) - { - attributeCount = Utility.RandomMinMax(2, 5); - min = 40; - max = 80; - } - else if (rnd < 6) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 30; - max = 60; - } - else if (rnd < 10) - { - attributeCount = Utility.RandomMinMax(1, 3); - min = 20; - max = 40; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } + attributeCount = Utility.RandomMinMax(3, 5); + min = 50; + max = 100; + } + else if (rnd < 3) + { + attributeCount = Utility.RandomMinMax(2, 5); + min = 40; + max = 80; + } + else if (rnd < 6) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 30; + max = 60; + } + else if (rnd < 10) + { + attributeCount = Utility.RandomMinMax(1, 3); + min = 20; + max = 40; } else { - if (rnd < 1) - { - attributeCount = Utility.RandomMinMax(2, 5); - min = 20; - max = 70; - } - else if (rnd < 3) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 20; - max = 50; - } - else if (rnd < 6) - { - attributeCount = Utility.RandomMinMax(2, 3); - min = 20; - max = 40; - } - else if (rnd < 10) - { - attributeCount = Utility.RandomMinMax(1, 2); - min = 10; - max = 30; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } + attributeCount = 1; + min = 10; + max = 20; } + + return; } - public static void Fill(LockableContainer cont, int level) + if (rnd < 1) { - cont.Movable = false; - cont.Locked = true; - int numberItems; + attributeCount = Utility.RandomMinMax(2, 5); + min = 20; + max = 70; + } + else if (rnd < 3) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 20; + max = 50; + } + else if (rnd < 6) + { + attributeCount = Utility.RandomMinMax(2, 3); + min = 20; + max = 40; + } + else if (rnd < 10) + { + attributeCount = Utility.RandomMinMax(1, 2); + min = 10; + max = 30; + } + else + { + attributeCount = 1; + min = 10; + max = 20; + } + } - if (level == 0) + public static void Fill(LockableContainer cont, int level) + { + cont.Movable = false; + cont.Locked = true; + + if (level == 0) + { + cont.LockLevel = 0; + + cont.DropItem(new Gold(Utility.RandomMinMax(50, 100))); + + if (Utility.RandomDouble() < 0.75) { - cont.LockLevel = 0; // Can't be unlocked - - cont.DropItem(new Gold(Utility.RandomMinMax(50, 100))); - - if (Utility.RandomDouble() < 0.75) - { - cont.DropItem(new TreasureMap(0, Map.Trammel)); - } + cont.DropItem(new TreasureMap(0, Map.Trammel)); } - else + } + else + { + cont.TrapType = TrapType.ExplosionTrap; + cont.TrapPower = level * 25; + cont.TrapLevel = level; + + cont.RequiredSkill = level switch { - cont.TrapType = TrapType.ExplosionTrap; - cont.TrapPower = level * 25; - cont.TrapLevel = level; + 1 => 36, + 2 => 76, + 3 => 84, + 4 => 92, + 5 => 100, + _ => 100 + }; - cont.RequiredSkill = level switch + cont.LockLevel = cont.RequiredSkill - 10; + cont.MaxLockLevel = cont.RequiredSkill + 40; + + // Publish 67 gold change + // if (Core.SA) + // cont.DropItem( new Gold( level * 5000 ) ); + // else + cont.DropItem(new Gold(level * 1000)); + + for (var i = 0; i < level * 5; ++i) + { + cont.DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular)); + } + + var numberItems = Core.SE ? level switch + { + 1 => 5, + 2 => 10, + 3 => 15, + 4 => 38, + 5 => 50, + 6 => 60, + _ => 0 + } : level * 6; + + for (var i = 0; i < numberItems; ++i) + { + var item = Core.AOS + ? Loot.RandomArmorOrShieldOrWeaponOrJewelry() + : Loot.RandomArmorOrShieldOrWeapon(); + + if (item is BaseWeapon weapon) { - 1 => 36, - 2 => 76, - 3 => 84, - 4 => 92, - 5 => 100, - 6 => 100, - _ => cont.RequiredSkill - }; - - cont.LockLevel = cont.RequiredSkill - 10; - cont.MaxLockLevel = cont.RequiredSkill + 40; - - // Publish 67 gold change - // if (Core.SA) - // cont.DropItem( new Gold( level * 5000 ) ); - // else - cont.DropItem(new Gold(level * 1000)); - - for (var i = 0; i < level * 5; ++i) - { - cont.DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular)); - } - - if (Core.SE) - { - numberItems = level switch - { - 1 => 5, - 2 => 10, - 3 => 15, - 4 => 38, - 5 => 50, - 6 => 60, - _ => 0 - }; - } - else - { - numberItems = level * 6; - } - - for (var i = 0; i < numberItems; ++i) - { - Item item; - if (Core.AOS) { - item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); } else { - item = Loot.RandomArmorOrShieldOrWeapon(); + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); } - if (item is BaseWeapon weapon) - { - if (Core.AOS) - { - GetRandomAOSStats(out var attributeCount, out var min, out var max); - BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); - } - - cont.DropItem(weapon); - } - else if (item is BaseArmor armor) - { - if (Core.AOS) - { - GetRandomAOSStats(out var attributeCount, out var min, out var max); - BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); - } - else - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); - } - - cont.DropItem(armor); - } - else if (item is BaseHat hat) - { - if (Core.AOS) - { - GetRandomAOSStats(out var attributeCount, out var min, out var max); - BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); - } - - cont.DropItem(hat); - } - else if (item is BaseJewel jewel) + cont.DropItem(weapon); + } + else if (item is BaseArmor armor) + { + if (Core.AOS) { GetRandomAOSStats(out var attributeCount, out var min, out var max); - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - - cont.DropItem(jewel); + BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); } - } - } - - int reagents; - if (level == 0) - { - reagents = 12; - } - else - { - reagents = level * 3; - } - - for (var i = 0; i < reagents; i++) - { - var item = Loot.RandomPossibleReagent(); - item.Amount = Utility.RandomMinMax(40, 60); - cont.DropItem(item); - } - - int gems; - if (level == 0) - { - gems = 2; - } - else - { - gems = level * 3; - } - - for (var i = 0; i < gems; i++) - { - var item = Loot.RandomGem(); - cont.DropItem(item); - } - - if (level == 6 && Core.AOS) - { - cont.DropItem(Artifacts.RandomElement().CreateInstance()); - } - } - - public override bool CheckLocked(Mobile from) - { - if (!Locked) - { - return false; - } - - if (Level == 0 && from.AccessLevel < AccessLevel.GameMaster) - { - foreach (var m in Guardians) - { - if (m.Alive) + else { - from.SendLocalizedMessage( - 1046448 - ); // You must first kill the guardians before you may open this chest. - return true; + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); } + + cont.DropItem(armor); } + else if (item is BaseHat hat) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); + } - LockPick(from); - return false; + cont.DropItem(hat); + } + else if (item is BaseJewel jewel) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + + cont.DropItem(jewel); + } } - - return base.CheckLocked(from); } - private bool CheckLoot(Mobile m, bool criminalAction) + var reagents = level == 0 ? 12 : level * 3; + + for (var i = 0; i < reagents; i++) { - if (Temporary) - { - return false; - } + var item = Loot.RandomPossibleReagent(); + item.Amount = Utility.RandomMinMax(40, 60); + cont.DropItem(item); + } - if (m.AccessLevel >= AccessLevel.GameMaster || Owner == null || m == Owner) - { - return true; - } + var gems = level == 0 ? 2 : level * 3; - if (Party.Get(Owner)?.Contains(m) == true) - { - return true; - } + for (var i = 0; i < gems; i++) + { + var item = Loot.RandomGem(); + cont.DropItem(item); + } - var map = Map; + if (level == 6 && Core.AOS) + { + cont.DropItem(Artifacts.RandomElement().CreateInstance()); + } + } - if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) - { - if (criminalAction) - { - m.CriminalAction(true); - } - else - { - m.SendLocalizedMessage(1010630); // Taking someone else's treasure is a criminal offense! - } - - return true; - } - - m.SendLocalizedMessage(1010631); // You did not discover this chest! + public override bool CheckLocked(Mobile from) + { + if (!Locked) + { return false; } - public override bool CheckItemUse(Mobile from, Item item) => - CheckLoot(from, item != this) && base.CheckItemUse(from, item); - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => - CheckLoot(from, true) && base.CheckLift(from, item, ref reject); - - public override void OnItemLifted(Mobile from, Item item) + if (_level == 0 && from.AccessLevel < AccessLevel.GameMaster) { - var notYetLifted = !m_Lifted.Contains(item); - - from.RevealingAction(); - - if (notYetLifted) + foreach (var m in _guardians) { - m_Lifted.Add(item); - - if (Utility.RandomDouble() <= 0.1) // 10% chance to spawn a new monster + if (m.Alive) { - TreasureMap.Spawn(Level, GetWorldLocation(), Map, from, false); + // You must first kill the guardians before you may open this chest. + from.SendLocalizedMessage(1046448); + return true; } } - base.OnItemLifted(from, item); + LockPick(from); + return false; } - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) - { - if (m.AccessLevel < AccessLevel.GameMaster) - { - m.SendLocalizedMessage(1048122, "", 0x8A5); // The chest refuses to be filled with treasure again. - return false; - } + return base.CheckLocked(from); + } - return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + private bool CheckLoot(Mobile m, bool criminalAction) + { + if (_temporary) + { + return false; } - public override void Serialize(IGenericWriter writer) + if (m.AccessLevel >= AccessLevel.GameMaster || _owner == null || m == _owner) { - base.Serialize(writer); - - writer.Write(2); // version - - Guardians.Tidy(); - writer.Write(Guardians); - writer.Write(Temporary); - - writer.Write(Owner); - - writer.Write(Level); - writer.WriteDeltaTime(DeleteTime); - m_Lifted.Tidy(); - writer.Write(m_Lifted); + return true; } - public override void Deserialize(IGenericReader reader) + if (Party.Get(_owner)?.Contains(m) == true) { - base.Deserialize(reader); + return true; + } - var version = reader.ReadInt(); + var map = Map; - switch (version) + if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) + { + if (criminalAction) { - case 2: - { - Guardians = reader.ReadEntityList(); - Temporary = reader.ReadBool(); - - goto case 1; - } - case 1: - { - Owner = reader.ReadEntity(); - - goto case 0; - } - case 0: - { - Level = reader.ReadInt(); - DeleteTime = reader.ReadDeltaTime(); - m_Lifted = reader.ReadEntityList(); - - if (version < 2) - { - Guardians = new List(); - } - - break; - } - } - - if (!Temporary) - { - m_Timer = new DeleteTimer(this, DeleteTime); - m_Timer.Start(); + m.CriminalAction(true); } else { - Delete(); + m.SendLocalizedMessage(1010630); // Taking someone else's treasure is a criminal offense! } + + return true; } - public override void OnAfterDelete() + m.SendLocalizedMessage(1010631); // You did not discover this chest! + return false; + } + + public override bool CheckItemUse(Mobile from, Item item) => + CheckLoot(from, item != this) && base.CheckItemUse(from, item); + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => + CheckLoot(from, true) && base.CheckLift(from, item, ref reject); + + public override void OnItemLifted(Mobile from, Item item) + { + var notYetLifted = !_lifted.Contains(item); + + from.RevealingAction(); + + if (notYetLifted) { - m_Timer?.Stop(); + _lifted.Add(item); - m_Timer = null; - - base.OnAfterDelete(); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) + if (Utility.RandomDouble() <= 0.1) // 10% chance to spawn a new monster { - list.Add(new RemoveEntry(from, this)); + TreasureMap.Spawn(_level, GetWorldLocation(), Map, from, false); } } - public void BeginRemove(Mobile from) - { - if (!from.Alive) - { - return; - } + base.OnItemLifted(from, item); + } - from.CloseGump(); - from.SendGump(new RemoveGump(from, this)); + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + { + if (m.AccessLevel < AccessLevel.GameMaster) + { + m.SendLocalizedMessage(1048122, "", 0x8A5); // The chest refuses to be filled with treasure again. + return false; } - public void EndRemove(Mobile from) - { - if (Deleted || from != Owner || !from.InRange(GetWorldLocation(), 3)) - { - return; - } + return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + } - from.SendLocalizedMessage(1048124, "", 0x8A5); // The old, rusted chest crumbles when you hit it. + private void Deserialize(IGenericReader reader, int version) + { + _guardians = new List(); + + _owner = reader.ReadEntity(); + _level = reader.ReadInt(); + var expireTimerNext = reader.ReadDeltaTime(); + DeserializeExpireTimer(expireTimerNext == DateTime.MinValue ? TimeSpan.MinValue : expireTimerNext - Core.Now); + _lifted = reader.ReadEntitySet(); + } + + [AfterDeserialization(false)] + private void AfterDeserialization() + { + if (_expireTimer == null) + { Delete(); } + } - private class RemoveGump : Gump + public override void OnAfterDelete() + { + _expireTimer?.Stop(); + _expireTimer = null; + base.OnAfterDelete(); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) { - private readonly TreasureMapChest m_Chest; - private readonly Mobile m_From; + list.Add(new RemoveEntry(from, this)); + } + } - public RemoveGump(Mobile from, TreasureMapChest chest) : base(15, 15) - { - m_From = from; - m_Chest = chest; - - Closable = false; - Disposable = false; - - AddPage(0); - - AddBackground(30, 0, 240, 240, 2620); - - AddHtmlLocalized( - 45, - 15, - 200, - 80, - 1048125, - 0xFFFFFF - ); // When this treasure chest is removed, any items still inside of it will be lost. - AddHtmlLocalized(45, 95, 200, 60, 1048126, 0xFFFFFF); // Are you certain you're ready to remove this chest? - - AddButton(40, 153, 4005, 4007, 1); - AddHtmlLocalized(75, 155, 180, 40, 1048127, 0xFFFFFF); // Remove the Treasure Chest - - AddButton(40, 195, 4005, 4007, 2); - AddHtmlLocalized(75, 197, 180, 35, 1006045, 0xFFFFFF); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - { - m_Chest.EndRemove(m_From); - } - } + public void BeginRemove(Mobile from) + { + if (!from.Alive) + { + return; } - private class RemoveEntry : ContextMenuEntry + from.CloseGump(); + from.SendGump(new RemoveGump(from, this)); + } + + public void EndRemove(Mobile from) + { + if (Deleted || from != _owner || !from.InRange(GetWorldLocation(), 3)) { - private readonly TreasureMapChest m_Chest; - private readonly Mobile m_From; - - public RemoveEntry(Mobile from, TreasureMapChest chest) : base(6149, 3) - { - m_From = from; - m_Chest = chest; - - Enabled = from == chest.Owner; - } - - public override void OnClick() - { - if (m_Chest.Deleted || m_From != m_Chest.Owner || !m_From.CheckAlive()) - { - return; - } - - m_Chest.BeginRemove(m_From); - } + return; } - private class DeleteTimer : Timer + from.SendLocalizedMessage(1048124, "", 0x8A5); // The old, rusted chest crumbles when you hit it. + Delete(); + } + + private class RemoveGump : Gump + { + private readonly TreasureMapChest _chest; + private readonly Mobile _from; + + public RemoveGump(Mobile from, TreasureMapChest chest) : base(15, 15) { - private readonly Item m_Item; + _from = from; + _chest = chest; - public DeleteTimer(Item item, DateTime time) : base(time - Core.Now) - { - m_Item = item; - } + Closable = false; + Disposable = false; - protected override void OnTick() + AddPage(0); + + AddBackground(30, 0, 240, 240, 2620); + + // When this treasure chest is removed, any items still inside of it will be lost. + AddHtmlLocalized(45, 15, 200, 80, 1048125, 0xFFFFFF); + // Are you certain you're ready to remove this chest? + AddHtmlLocalized(45, 95, 200, 60, 1048126, 0xFFFFFF); + + AddButton(40, 153, 4005, 4007, 1); + AddHtmlLocalized(75, 155, 180, 40, 1048127, 0xFFFFFF); // Remove the Treasure Chest + + AddButton(40, 195, 4005, 4007, 2); + AddHtmlLocalized(75, 197, 180, 35, 1006045, 0xFFFFFF); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) { - m_Item.Delete(); + _chest.EndRemove(_from); } } } + + private class RemoveEntry : ContextMenuEntry + { + private readonly TreasureMapChest _chest; + private readonly Mobile _from; + + public RemoveEntry(Mobile from, TreasureMapChest chest) : base(6149, 3) + { + _from = from; + _chest = chest; + + Enabled = from == chest._owner; + } + + public override void OnClick() + { + if (_chest.Deleted || _from != _chest._owner || !_from.CheckAlive()) + { + return; + } + + _chest.BeginRemove(_from); + } + } } diff --git a/Projects/UOContent/Migrations/Server.Items.TreasureMapChest.v2.json b/Projects/UOContent/Migrations/Server.Items.TreasureMapChest.v2.json new file mode 100644 index 000000000..9bf36d71a --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.TreasureMapChest.v2.json @@ -0,0 +1,55 @@ +{ + "version": 2, + "type": "Server.Items.TreasureMapChest", + "properties": [ + { + "name": "Guardians", + "type": "System.Collections.Generic.List\u003CServer.Mobile\u003E", + "rule": "ListMigrationRule", + "ruleArguments": [ + "", + "Server.Mobile", + "SerializableInterfaceMigrationRule" + ] + }, + { + "name": "Temporary", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Owner", + "type": "Server.Mobile", + "rule": "SerializableInterfaceMigrationRule" + }, + { + "name": "Level", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "ExpireTimer", + "type": "Server.Timer", + "rule": "TimerMigrationRule", + "ruleArguments": [ + "@TimerDrift" + ] + }, + { + "name": "Lifted", + "type": "System.Collections.Generic.HashSet\u003CServer.Item\u003E", + "rule": "HashSetMigrationRule", + "ruleArguments": [ + "@Tidy", + "Server.Item", + "SerializableInterfaceMigrationRule" + ] + } + ] +} \ No newline at end of file