diff --git a/Projects/Server/Text/TextDefinitionExtensions.cs b/Projects/Server/Text/TextDefinitionExtensions.cs index af93ad833..ddf95dfe4 100644 --- a/Projects/Server/Text/TextDefinitionExtensions.cs +++ b/Projects/Server/Text/TextDefinitionExtensions.cs @@ -155,5 +155,22 @@ public static class TextDefinitionExtensions } } + public static void PublicOverheadMessage(this TextDefinition def, Item item, MessageType messageType, int hue) + { + if (def == null) + { + return; + } + + if (def.Number > 0) + { + item.PublicOverheadMessage(messageType, hue, def.Number); + } + else if (def.String != null) + { + item.PublicOverheadMessage(messageType, hue, false, def.String); + } + } + public static bool IsNullOrEmpty(this TextDefinition def) => def?.IsEmpty != false; } diff --git a/Projects/UOContent/Commands/Object Creation/Decorate.cs b/Projects/UOContent/Commands/Object Creation/Decorate.cs index 25c311cd6..4922160dc 100644 --- a/Projects/UOContent/Commands/Object Creation/Decorate.cs +++ b/Projects/UOContent/Commands/Object Creation/Decorate.cs @@ -261,8 +261,8 @@ namespace Server.Commands var hi = new HintItem(m_ItemID, range, messageNumber, hintNumber); - hi.WarningString = messageString; - hi.HintString = hintString; + hi.WarningMessage = messageString; + hi.HintMessage = hintString; hi.ResetDelay = resetDelay; item = hi; @@ -316,7 +316,7 @@ namespace Server.Commands var wi = new WarningItem(m_ItemID, range, messageNumber); - wi.WarningString = messageString; + wi.WarningMessage = messageString; wi.ResetDelay = resetDelay; item = wi; @@ -687,7 +687,7 @@ namespace Server.Commands if (indexOf >= 0) { - st.MessageString = m_Params[i][++indexOf..]; + st.Message = m_Params[i][++indexOf..]; } } else if (m_Params[i].StartsWithOrdinal("MessageNumber")) @@ -696,7 +696,7 @@ namespace Server.Commands if (indexOf >= 0) { - st.MessageNumber = Utility.ToInt32(m_Params[i].AsSpan()[++indexOf..]); + st.Message = Utility.ToInt32(m_Params[i].AsSpan()[++indexOf..]); } } else if (m_Params[i].StartsWithOrdinal("PointDest")) diff --git a/Projects/UOContent/Commands/Object Creation/DecorateMag.cs b/Projects/UOContent/Commands/Object Creation/DecorateMag.cs index 3160147f6..32dfde881 100644 --- a/Projects/UOContent/Commands/Object Creation/DecorateMag.cs +++ b/Projects/UOContent/Commands/Object Creation/DecorateMag.cs @@ -257,8 +257,8 @@ namespace Server.Commands var hi = new HintItem(m_ItemID, range, messageNumber, hintNumber); - hi.WarningString = messageString; - hi.HintString = hintString; + hi.WarningMessage = messageString; + hi.HintMessage = hintString; hi.ResetDelay = resetDelay; item = hi; @@ -312,7 +312,7 @@ namespace Server.Commands var wi = new WarningItem(m_ItemID, range, messageNumber); - wi.WarningString = messageString; + wi.WarningMessage = messageString; wi.ResetDelay = resetDelay; item = wi; @@ -683,7 +683,7 @@ namespace Server.Commands if (indexOf >= 0) { - st.MessageString = m_Params[i][++indexOf..]; + st.Message = m_Params[i][++indexOf..]; } } else if (m_Params[i].StartsWithOrdinal("MessageNumber")) @@ -692,7 +692,7 @@ namespace Server.Commands if (indexOf >= 0) { - st.MessageNumber = Utility.ToInt32(m_Params[i].AsSpan()[++indexOf..]); + st.Message = Utility.ToInt32(m_Params[i].AsSpan()[++indexOf..]); } } else if (m_Params[i].StartsWithOrdinal("PointDest")) diff --git a/Projects/UOContent/Items/Misc/PowerGenerator.cs b/Projects/UOContent/Items/Misc/PowerGenerator.cs index 4af1ad788..70bc92131 100644 --- a/Projects/UOContent/Items/Misc/PowerGenerator.cs +++ b/Projects/UOContent/Items/Misc/PowerGenerator.cs @@ -1,600 +1,541 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.Gumps; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0)] +public partial class PowerGenerator : BaseAddon { - public class PowerGenerator : BaseAddon + [Constructible] + public PowerGenerator() : this(Utility.RandomMinMax(3, 6)) { - [Constructible] - public PowerGenerator() : this(Utility.RandomMinMax(3, 6)) + } + + [Constructible] + public PowerGenerator(int sideLength) + { + AddGeneratorComponent(0x4FA1, 0, 0, 0); + AddGeneratorComponent(0x76, -1, 0, 0); + AddGeneratorComponent(0x75, 0, -1, 0); + AddGeneratorComponent(0x37F4, 0, 0, 13); + + AddComponent(new ControlPanel(sideLength), 1, 0, -2); + } + + public override bool ShareHue => false; + + private void AddGeneratorComponent(int itemID, int x, int y, int z) + { + var component = new AddonComponent(itemID); + component.Name = "a power generator"; + component.Hue = 0x451; + + AddComponent(component, x, y, z); + } +} + +[SerializationGenerator(1)] +public partial class ControlPanel : AddonComponent +{ + private static readonly TimeSpan m_UseTimeout = TimeSpan.FromMinutes(2.0); + + private readonly HashSet m_DamageTable = new(); + private DateTime m_LastUse; + + private int m_SideLength; + + private Mobile m_User; + + [SerializableField(1, setter: "private")] + private Point2D[] _path; + + public ControlPanel(int sideLength) : base(0xBDC) + { + Hue = 0x835; + + m_SideLength = sideLength; + } + + [SerializableProperty(0, useField: nameof(m_SideLength))] + [CommandProperty(AccessLevel.GameMaster)] + public int SideLength + { + get => m_SideLength; + set { - } + value = Math.Clamp(value, 3, 6); - [Constructible] - public PowerGenerator(int sideLength) - { - AddGeneratorComponent(0x4FA1, 0, 0, 0); - AddGeneratorComponent(0x76, -1, 0, 0); - AddGeneratorComponent(0x75, 0, -1, 0); - AddGeneratorComponent(0x37F4, 0, 0, 13); - - AddComponent(new ControlPanel(sideLength), 1, 0, -2); - } - - public PowerGenerator(Serial serial) : base(serial) - { - } - - public override bool ShareHue => false; - - private void AddGeneratorComponent(int itemID, int x, int y, int z) - { - var component = new AddonComponent(itemID); - component.Name = "a power generator"; - component.Hue = 0x451; - - AddComponent(component, x, y, z); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadEncodedInt(); + if (m_SideLength != value) + { + m_SideLength = value; + InitPath(); + this.MarkDirty(); + } } } - public class ControlPanel : AddonComponent + public override string DefaultName => "a control panel"; + + public void InitPath() { - private static readonly TimeSpan m_UseTimeout = TimeSpan.FromMinutes(2.0); + // Depth-First Search algorithm - private readonly HashSet m_DamageTable = new(); - private DateTime m_LastUse; + var totalNodes = SideLength * SideLength; - private int m_SideLength; + var stack = new Point2D[totalNodes]; + var current = stack[0] = new Point2D(0, 0); + var stackSize = 1; - private Mobile m_User; + var visited = new bool[SideLength, SideLength]; + visited[0, 0] = true; - public ControlPanel(int sideLength) : base(0xBDC) + while (true) { - Hue = 0x835; + var choices = new PathDirection[4]; + var count = 0; - SideLength = sideLength; - } - - public ControlPanel(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SideLength - { - get => m_SideLength; - set + if (current.X > 0 && !visited[current.X - 1, current.Y]) { - if (value < 3) - { - value = 3; - } - else if (value > 6) - { - value = 6; - } - - if (m_SideLength != value) - { - m_SideLength = value; - InitPath(); - } - } - } - - public Node[] Path { get; private set; } - - public override string DefaultName => "a control panel"; - - public void InitPath() - { - // Depth-First Search algorithm - - var totalNodes = SideLength * SideLength; - - var stack = new Node[totalNodes]; - var current = stack[0] = new Node(0, 0); - var stackSize = 1; - - var visited = new bool[SideLength, SideLength]; - visited[0, 0] = true; - - while (true) - { - var choices = new PathDirection[4]; - var count = 0; - - if (current.X > 0 && !visited[current.X - 1, current.Y]) - { - choices[count++] = PathDirection.Left; - } - - if (current.Y > 0 && !visited[current.X, current.Y - 1]) - { - choices[count++] = PathDirection.Up; - } - - if (current.X < SideLength - 1 && !visited[current.X + 1, current.Y]) - { - choices[count++] = PathDirection.Right; - } - - if (current.Y < SideLength - 1 && !visited[current.X, current.Y + 1]) - { - choices[count++] = PathDirection.Down; - } - - if (count > 0) - { - var dir = choices[Utility.Random(count)]; - - current = dir switch - { - PathDirection.Left => new Node(current.X - 1, current.Y), - PathDirection.Up => new Node(current.X, current.Y - 1), - PathDirection.Right => new Node(current.X + 1, current.Y), - _ => new Node(current.X, current.Y + 1) - }; - - stack[stackSize++] = current; - - if (current.X == SideLength - 1 && current.Y == SideLength - 1) - { - break; - } - - visited[current.X, current.Y] = true; - } - else - { - current = stack[--stackSize - 1]; - } + choices[count++] = PathDirection.Left; } - Path = new Node[stackSize]; - - for (var i = 0; i < stackSize; i++) + if (current.Y > 0 && !visited[current.X, current.Y - 1]) { - Path[i] = stack[i]; + choices[count++] = PathDirection.Up; } - if (m_User != null) + if (current.X < SideLength - 1 && !visited[current.X + 1, current.Y]) { - m_User.CloseGump(); - m_User = null; - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(this, 3)) - { - from.SendLocalizedMessage(500446); // That is too far away. - return; + choices[count++] = PathDirection.Right; } - if (m_User != null) + if (current.Y < SideLength - 1 && !visited[current.X, current.Y + 1]) { - if (m_User == from) + choices[count++] = PathDirection.Down; + } + + if (count > 0) + { + var dir = choices[Utility.Random(count)]; + + current = dir switch { - return; - } - - if (m_User.Deleted || m_User.Map != Map || !m_User.InRange(this, 3) - || m_User.NetState == null || Core.Now - m_LastUse >= m_UseTimeout) - { - m_User.CloseGump(); - } - else - { - from.SendMessage("Someone is currently using the control panel."); - return; - } - } - - m_User = from; - m_LastUse = Core.Now; - - from.SendGump(new GameGump(this, from, 0, false)); - } - - public void DoDamage(Mobile to) - { - to.NetState.SendMessage( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - false, - "ENU", - "", - "The generator shoots an arc of electricity at you!" - ); - - to.BoltEffect(0); - to.LocalOverheadMessage(MessageType.Regular, 0xC9, true, "* Your body convulses from electric shock *"); - to.NonlocalOverheadMessage(MessageType.Regular, 0xC9, true, $"* {to.Name} spasms from electric shock *"); - - AOS.Damage(to, to, 60, 0, 0, 0, 0, 100); - - if (!to.Alive) - { - return; - } - - if (!m_DamageTable.Contains(to)) - { - to.Frozen = true; - - var timer = new DamageTimer(this, to); - m_DamageTable.Add(to); - - timer.Start(); - } - } - - public void Solve(Mobile from) - { - Effects.PlaySound(Location, Map, 0x211); - Effects.PlaySound(Location, Map, 0x1F3); - - Effects.SendLocationEffect(Location, Map, 0x36B0, 4, 4); - Effects.SendLocationEffect(new Point3D(X - 1, Y - 1, Z + 2), Map, 0x36B0, 4, 4); - Effects.SendLocationEffect(new Point3D(X - 2, Y - 1, Z + 2), Map, 0x36B0, 4, 4); - - from.SendMessage("You scrounge some gems from the wreckage."); - - for (var i = 0; i < SideLength; i++) - { - from.AddToBackpack(new ArcaneGem()); - } - - from.AddToBackpack(new Diamond(SideLength)); - - Item ore = new ShadowIronOre(9); - ore.MoveToWorld(new Point3D(X - 1, Y, Z + 2), Map); - - ore = new ShadowIronOre(14); - ore.MoveToWorld(new Point3D(X - 2, Y - 1, Z + 2), Map); - - Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_SideLength); - - writer.WriteEncodedInt(Path.Length); - for (var i = 0; i < Path.Length; i++) - { - var cur = Path[i]; - - writer.WriteEncodedInt(cur.X); - writer.WriteEncodedInt(cur.Y); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadEncodedInt(); - - m_SideLength = reader.ReadEncodedInt(); - - Path = new Node[reader.ReadEncodedInt()]; - for (var i = 0; i < Path.Length; i++) - { - Path[i] = new Node(reader.ReadEncodedInt(), reader.ReadEncodedInt()); - } - } - - public struct Node - { - public int X { get; set; } - - public int Y { get; set; } - - public Node(int x, int y) - { - X = x; - Y = y; - } - } - - private enum PathDirection - { - Left, - Up, - Right, - Down - } - - private class GameGump : Gump - { - private readonly Mobile m_From; - - private readonly ControlPanel m_Panel; - private readonly int m_Step; - - public GameGump(ControlPanel panel, Mobile from, int step, bool hint) : base(5, 30) - { - m_Panel = panel; - m_From = from; - m_Step = step; - - var sideLength = panel.SideLength; - - AddBackground(50, 0, 530, 410, 0xA28); - - AddImage(0, 0, 0x28C8); - AddImage(547, 0, 0x28C9); - - AddBackground(95, 20, 442, 90, 0xA28); - - AddHtml(229, 35, 300, 45, "GENERATOR CONTROL PANEL"); - - AddHtml(223, 60, 300, 70, "Use the Directional Controls to"); - AddHtml(253, 75, 300, 85, "Close the Grid Circuit"); - - AddImage(140, 40, 0x28D3); - AddImage(420, 40, 0x28D3); - - AddBackground(365, 120, 178, 210, 0x1400); - - AddImage(365, 115, 0x28D4); - AddImage(365, 288, 0x28D4); - - AddImage(414, 189, 0x589); - AddImage(435, 210, 0xA52); - - AddButton(408, 222, 0x29EA, 0x29EC, 1); // Left - AddButton(448, 185, 0x29CC, 0x29CE, 2); // Up - AddButton(473, 222, 0x29D6, 0x29D8, 3); // Right - AddButton(448, 243, 0x29E0, 0x29E2, 4); // Down - - AddBackground(90, 115, 30 + 40 * sideLength, 30 + 40 * sideLength, 0xA28); - AddBackground(100, 125, 10 + 40 * sideLength, 10 + 40 * sideLength, 0x1400); - - for (var i = 0; i < sideLength; i++) - { - for (var j = 0; j < sideLength - 1; j++) - { - AddImage(120 + 40 * i, 162 + 40 * j, 0x13F9); - } - } - - for (var i = 0; i < sideLength - 1; i++) - { - for (var j = 0; j < sideLength; j++) - { - AddImage(138 + 40 * i, 147 + 40 * j, 0x13FD); - } - } - - var path = panel.Path; - - var hues = new NodeHue[sideLength, sideLength]; - - for (var i = 0; i <= step; i++) - { - var n = path[i]; - hues[n.X, n.Y] = NodeHue.Blue; - } - - var lastNode = path[^1]; - hues[lastNode.X, lastNode.Y] = NodeHue.Red; - - for (var i = 0; i < sideLength; i++) - { - for (var j = 0; j < sideLength; j++) - { - AddNode(110 + 40 * i, 135 + 40 * j, hues[i, j]); - } - } - - var curNode = path[step]; - AddImage(118 + 40 * curNode.X, 143 + 40 * curNode.Y, 0x13A8); - - if (hint) - { - var nextNode = path[step + 1]; - AddImage(119 + 40 * nextNode.X, 143 + 40 * nextNode.Y, 0x939); - } - - if (from.Skills.Lockpicking.Value >= 65.0) - { - AddButton(365, 350, 0xFA6, 0xFA7, 5); - AddHtml(405, 345, 140, 40, "Attempt to Decipher the Circuit Path"); - } - } - - private void AddNode(int x, int y, NodeHue hue) - { - var id = hue switch - { - NodeHue.Gray => 0x25F8, - NodeHue.Blue => 0x868, - _ => 0x9A8 + PathDirection.Left => new Point2D(current.X - 1, current.Y), + PathDirection.Up => new Point2D(current.X, current.Y - 1), + PathDirection.Right => new Point2D(current.X + 1, current.Y), + _ => new Point2D(current.X, current.Y + 1) }; - AddImage(x, y, id); + stack[stackSize++] = current; + + if (current.X == SideLength - 1 && current.Y == SideLength - 1) + { + break; + } + + visited[current.X, current.Y] = true; + } + else + { + current = stack[--stackSize - 1]; + } + } + + Path = new Point2D[stackSize]; + + for (var i = 0; i < stackSize; i++) + { + Path[i] = stack[i]; + } + + if (m_User != null) + { + m_User.CloseGump(); + m_User = null; + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(this, 3)) + { + from.SendLocalizedMessage(500446); // That is too far away. + return; + } + + if (m_User != null) + { + if (m_User == from) + { + return; } - public override void OnResponse(NetState sender, RelayInfo info) + if (m_User.Deleted || m_User.Map != Map || !m_User.InRange(this, 3) + || m_User.NetState == null || Core.Now - m_LastUse >= m_UseTimeout) { - if (m_Panel.Deleted || info.ButtonID == 0 || !m_From.CheckAlive()) + m_User.CloseGump(); + } + else + { + from.SendMessage("Someone is currently using the control panel."); + return; + } + } + + m_User = from; + m_LastUse = Core.Now; + + from.SendGump(new GameGump(this, from, 0, false)); + } + + public void DoDamage(Mobile to) + { + to.NetState.SendMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + false, + "ENU", + "", + "The generator shoots an arc of electricity at you!" + ); + + to.BoltEffect(0); + to.LocalOverheadMessage(MessageType.Regular, 0xC9, true, "* Your body convulses from electric shock *"); + to.NonlocalOverheadMessage(MessageType.Regular, 0xC9, true, $"* {to.Name} spasms from electric shock *"); + + AOS.Damage(to, to, 60, 0, 0, 0, 0, 100); + + if (!to.Alive) + { + return; + } + + if (!m_DamageTable.Contains(to)) + { + to.Frozen = true; + + var timer = new DamageTimer(this, to); + m_DamageTable.Add(to); + + timer.Start(); + } + } + + public void Solve(Mobile from) + { + Effects.PlaySound(Location, Map, 0x211); + Effects.PlaySound(Location, Map, 0x1F3); + + Effects.SendLocationEffect(Location, Map, 0x36B0, 4, 4); + Effects.SendLocationEffect(new Point3D(X - 1, Y - 1, Z + 2), Map, 0x36B0, 4, 4); + Effects.SendLocationEffect(new Point3D(X - 2, Y - 1, Z + 2), Map, 0x36B0, 4, 4); + + from.SendMessage("You scrounge some gems from the wreckage."); + + for (var i = 0; i < SideLength; i++) + { + from.AddToBackpack(new ArcaneGem()); + } + + from.AddToBackpack(new Diamond(SideLength)); + + Item ore = new ShadowIronOre(9); + ore.MoveToWorld(new Point3D(X - 1, Y, Z + 2), Map); + + ore = new ShadowIronOre(14); + ore.MoveToWorld(new Point3D(X - 2, Y - 1, Z + 2), Map); + + Delete(); + } + + private void Deserialize(IGenericReader reader, int version) + { + m_SideLength = reader.ReadEncodedInt(); + + Path = new Point2D[reader.ReadEncodedInt()]; + for (var i = 0; i < Path.Length; i++) + { + Path[i] = new Point2D(reader.ReadEncodedInt(), reader.ReadEncodedInt()); + } + } + + private enum PathDirection + { + Left, + Up, + Right, + Down + } + + private class GameGump : Gump + { + private readonly Mobile m_From; + + private readonly ControlPanel m_Panel; + private readonly int m_Step; + + public GameGump(ControlPanel panel, Mobile from, int step, bool hint) : base(5, 30) + { + m_Panel = panel; + m_From = from; + m_Step = step; + + var sideLength = panel.SideLength; + + AddBackground(50, 0, 530, 410, 0xA28); + + AddImage(0, 0, 0x28C8); + AddImage(547, 0, 0x28C9); + + AddBackground(95, 20, 442, 90, 0xA28); + + AddHtml(229, 35, 300, 45, "GENERATOR CONTROL PANEL"); + + AddHtml(223, 60, 300, 70, "Use the Directional Controls to"); + AddHtml(253, 75, 300, 85, "Close the Grid Circuit"); + + AddImage(140, 40, 0x28D3); + AddImage(420, 40, 0x28D3); + + AddBackground(365, 120, 178, 210, 0x1400); + + AddImage(365, 115, 0x28D4); + AddImage(365, 288, 0x28D4); + + AddImage(414, 189, 0x589); + AddImage(435, 210, 0xA52); + + AddButton(408, 222, 0x29EA, 0x29EC, 1); // Left + AddButton(448, 185, 0x29CC, 0x29CE, 2); // Up + AddButton(473, 222, 0x29D6, 0x29D8, 3); // Right + AddButton(448, 243, 0x29E0, 0x29E2, 4); // Down + + AddBackground(90, 115, 30 + 40 * sideLength, 30 + 40 * sideLength, 0xA28); + AddBackground(100, 125, 10 + 40 * sideLength, 10 + 40 * sideLength, 0x1400); + + for (var i = 0; i < sideLength; i++) + { + for (var j = 0; j < sideLength - 1; j++) + { + AddImage(120 + 40 * i, 162 + 40 * j, 0x13F9); + } + } + + for (var i = 0; i < sideLength - 1; i++) + { + for (var j = 0; j < sideLength; j++) + { + AddImage(138 + 40 * i, 147 + 40 * j, 0x13FD); + } + } + + var path = panel.Path; + + var hues = new NodeHue[sideLength, sideLength]; + + for (var i = 0; i <= step; i++) + { + var n = path[i]; + hues[n.X, n.Y] = NodeHue.Blue; + } + + var lastNode = path[^1]; + hues[lastNode.X, lastNode.Y] = NodeHue.Red; + + for (var i = 0; i < sideLength; i++) + { + for (var j = 0; j < sideLength; j++) + { + AddNode(110 + 40 * i, 135 + 40 * j, hues[i, j]); + } + } + + var curNode = path[step]; + AddImage(118 + 40 * curNode.X, 143 + 40 * curNode.Y, 0x13A8); + + if (hint) + { + var nextNode = path[step + 1]; + AddImage(119 + 40 * nextNode.X, 143 + 40 * nextNode.Y, 0x939); + } + + if (from.Skills.Lockpicking.Value >= 65.0) + { + AddButton(365, 350, 0xFA6, 0xFA7, 5); + AddHtml(405, 345, 140, 40, "Attempt to Decipher the Circuit Path"); + } + } + + private void AddNode(int x, int y, NodeHue hue) + { + var id = hue switch + { + NodeHue.Gray => 0x25F8, + NodeHue.Blue => 0x868, + _ => 0x9A8 + }; + + AddImage(x, y, id); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Panel.Deleted || info.ButtonID == 0 || !m_From.CheckAlive()) + { + m_Panel.m_User = null; + return; + } + + if (m_From.Map != m_Panel.Map || !m_From.InRange(m_Panel, 3)) + { + m_From.SendLocalizedMessage(500446); // That is too far away. + m_Panel.m_User = null; + return; + } + + var nextNode = m_Panel.Path[m_Step + 1]; + + if (info.ButtonID == 5) // Attempt to Decipher + { + var lockpicking = m_From.Skills.Lockpicking.Value; + + if (lockpicking < 65.0) { - m_Panel.m_User = null; return; } - if (m_From.Map != m_Panel.Map || !m_From.InRange(m_Panel, 3)) + m_From.PlaySound(0x241); + + if (40.0 + Utility.RandomDouble() * 80.0 < lockpicking) { - m_From.SendLocalizedMessage(500446); // That is too far away. + m_From.SendGump(new GameGump(m_Panel, m_From, m_Step, true)); + m_Panel.m_LastUse = Core.Now; + } + else + { + m_Panel.DoDamage(m_From); m_Panel.m_User = null; - return; + } + } + else + { + var curNode = m_Panel.Path[m_Step]; + + int newX, newY; + switch (info.ButtonID) + { + case 1: // Left + { + newX = curNode.X - 1; + newY = curNode.Y; + break; + } + case 2: // Up + { + newX = curNode.X; + newY = curNode.Y - 1; + break; + } + case 3: // Right + { + newX = curNode.X + 1; + newY = curNode.Y; + break; + } + case 4: // Down + { + newX = curNode.X; + newY = curNode.Y + 1; + break; + } + + default: + { + return; + } } - var nextNode = m_Panel.Path[m_Step + 1]; - - if (info.ButtonID == 5) // Attempt to Decipher + if (nextNode.X == newX && nextNode.Y == newY) { - var lockpicking = m_From.Skills.Lockpicking.Value; - - if (lockpicking < 65.0) + if (m_Step + 1 == m_Panel.Path.Length - 1) { - return; - } - - m_From.PlaySound(0x241); - - if (40.0 + Utility.RandomDouble() * 80.0 < lockpicking) - { - m_From.SendGump(new GameGump(m_Panel, m_From, m_Step, true)); - m_Panel.m_LastUse = Core.Now; + m_Panel.Solve(m_From); + m_Panel.m_User = null; } else { - m_Panel.DoDamage(m_From); - m_Panel.m_User = null; + m_From.PlaySound(0x1F4); + m_From.SendGump(new GameGump(m_Panel, m_From, m_Step + 1, false)); + m_Panel.m_LastUse = Core.Now; } } else { - var curNode = m_Panel.Path[m_Step]; - - int newX, newY; - switch (info.ButtonID) - { - case 1: // Left - { - newX = curNode.X - 1; - newY = curNode.Y; - break; - } - case 2: // Up - { - newX = curNode.X; - newY = curNode.Y - 1; - break; - } - case 3: // Right - { - newX = curNode.X + 1; - newY = curNode.Y; - break; - } - case 4: // Down - { - newX = curNode.X; - newY = curNode.Y + 1; - break; - } - - default: - { - return; - } - } - - if (nextNode.X == newX && nextNode.Y == newY) - { - if (m_Step + 1 == m_Panel.Path.Length - 1) - { - m_Panel.Solve(m_From); - m_Panel.m_User = null; - } - else - { - m_From.PlaySound(0x1F4); - m_From.SendGump(new GameGump(m_Panel, m_From, m_Step + 1, false)); - m_Panel.m_LastUse = Core.Now; - } - } - else - { - m_Panel.DoDamage(m_From); - m_Panel.m_User = null; - } + m_Panel.DoDamage(m_From); + m_Panel.m_User = null; } } - - private enum NodeHue - { - Gray, - Blue, - Red - } } - private class DamageTimer : Timer + private enum NodeHue { - private readonly ControlPanel m_Panel; - private readonly Mobile m_To; - private int m_Step; + Gray, + Blue, + Red + } + } - public DamageTimer(ControlPanel panel, Mobile to) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) + private class DamageTimer : Timer + { + private readonly ControlPanel m_Panel; + private readonly Mobile m_To; + private int m_Step; + + public DamageTimer(ControlPanel panel, Mobile to) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) + { + m_Panel = panel; + m_To = to; + m_Step = 0; + } + + protected override void OnTick() + { + if (m_Panel.Deleted || m_To.Deleted || !m_To.Alive) { - m_Panel = panel; - m_To = to; - m_Step = 0; + End(); + return; } - protected override void OnTick() + m_To.PlaySound(0x28); + + m_To.LocalOverheadMessage(MessageType.Regular, 0xC9, true, "* Your body convulses from electric shock *"); + m_To.NonlocalOverheadMessage( + MessageType.Regular, + 0xC9, + true, + $"* {m_To.Name} spasms from electric shock *" + ); + + AOS.Damage(m_To, m_To, 20, 0, 0, 0, 0, 100); + + if (++m_Step >= 3 || !m_To.Alive) { - if (m_Panel.Deleted || m_To.Deleted || !m_To.Alive) - { - End(); - return; - } - - m_To.PlaySound(0x28); - - m_To.LocalOverheadMessage(MessageType.Regular, 0xC9, true, "* Your body convulses from electric shock *"); - m_To.NonlocalOverheadMessage( - MessageType.Regular, - 0xC9, - true, - $"* {m_To.Name} spasms from electric shock *" - ); - - AOS.Damage(m_To, m_To, 20, 0, 0, 0, 0, 100); - - if (++m_Step >= 3 || !m_To.Alive) - { - End(); - } + End(); } + } - private void End() - { - m_Panel.m_DamageTable.Remove(m_To); - m_To.Frozen = false; + private void End() + { + m_Panel.m_DamageTable.Remove(m_To); + m_To.Frozen = false; - Stop(); - } + Stop(); } } } diff --git a/Projects/UOContent/Items/Misc/Scales.cs b/Projects/UOContent/Items/Misc/Scales.cs index c08be8fc9..3fe4937df 100644 --- a/Projects/UOContent/Items/Misc/Scales.cs +++ b/Projects/UOContent/Items/Misc/Scales.cs @@ -1,86 +1,63 @@ +using ModernUO.Serialization; using Server.Targeting; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class Scales : Item { - public class Scales : Item + [Constructible] + public Scales() : base(0x1852) => Weight = 4.0; + + public override void OnDoubleClick(Mobile from) { - [Constructible] - public Scales() : base(0x1852) => Weight = 4.0; + from.SendLocalizedMessage(502431); // What would you like to weigh? + from.Target = new InternalTarget(this); + } - public Scales(Serial serial) : base(serial) + private class InternalTarget : Target + { + private Scales _scales; + + public InternalTarget(Scales item) : base(1, false, TargetFlags.None) => _scales = item; + + protected override void OnTarget(Mobile from, object targeted) { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(502431); // What would you like to weigh? - from.Target = new InternalTarget(this); - } - - private class InternalTarget : Target - { - private readonly Scales m_Item; - - public InternalTarget(Scales item) : base(1, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) + if (targeted == _scales) { - string message; + from.SendMessage("It cannot weigh itself."); + return; + } - if (targeted == m_Item) - { - message = "It cannot weight itself."; - } - else if (targeted is Item item) - { - var root = item.RootParent; + if (targeted is Mobile m) + { + from.SendLocalizedMessage(502432); // That is too heavy for these scales! + } - if (root != null && root != from || item.Parent == from) - { - message = "You decide that item's current location is too awkward to get an accurate result."; - } - else if (item.Movable) - { - message = item.Amount > 1 - ? "You place one item on the scale. " - : "You place that item on the scale. "; + if (targeted is not Item { Movable: true } item) + { + from.SendMessage("You cannot weigh that."); + return; + } - var weight = item.Weight; + var root = item.RootParent; - if (weight <= 0.0) - { - message += "It is lighter than a feather."; - } - else - { - message += $"It weighs {weight} stones."; - } - } - else - { - message = "You cannot weigh that object."; - } - } - else - { - message = "You cannot weigh that object."; - } + if (root != null && root != from || item.Parent == from) + { + from.SendMessage("You decide that item's current location is too awkward to get an accurate result."); + return; + } - from.SendMessage(message); + var amount = item.Amount > 1 ? "one" : "that"; + var weight = item.Weight; + + if (weight <= 0.0) + { + from.SendMessage($"You place {amount} item on the scale. It is lighter than a feather."); + } + else + { + from.SendMessage($"You place {amount} item on the scale. It weighs {weight} stones."); } } } diff --git a/Projects/UOContent/Items/Misc/SerpentPillar.cs b/Projects/UOContent/Items/Misc/SerpentPillar.cs index 2038aa244..4f990ba48 100644 --- a/Projects/UOContent/Items/Misc/SerpentPillar.cs +++ b/Projects/UOContent/Items/Misc/SerpentPillar.cs @@ -1,107 +1,81 @@ +using ModernUO.Serialization; using Server.Multis; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0)] +public partial class SerpentPillar : Item { - public class SerpentPillar : Item + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private bool _active; + + [SerializableField(1)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private string _word; + + [SerializableField(2)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private Rectangle2D _destination; + + [Constructible] + public SerpentPillar() : this(null, new Rectangle2D(), false) { - [Constructible] - public SerpentPillar() : this(null, new Rectangle2D(), false) + } + + public SerpentPillar(string word, Rectangle2D destination, bool active = true) : base(0x233F) + { + Movable = false; + _active = active; + _word = word; + _destination = destination; + } + + public override bool HandlesOnSpeech => true; + + public override void OnSpeech(SpeechEventArgs e) + { + var from = e.Mobile; + + if (!e.Handled && from.InRange(this, 10) && e.Speech.ToLower() == Word) { - } + var boat = BaseBoat.FindBoatAt(from.Location, from.Map); - public SerpentPillar(string word, Rectangle2D destination, bool active = true) : base(0x233F) - { - Movable = false; - - Active = active; - Word = word; - Destination = destination; - } - - public SerpentPillar(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Word { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Rectangle2D Destination { get; set; } - - public override bool HandlesOnSpeech => true; - - public override void OnSpeech(SpeechEventArgs e) - { - var from = e.Mobile; - - if (!e.Handled && from.InRange(this, 10) && e.Speech.ToLower() == Word) + if (boat == null) { - var boat = BaseBoat.FindBoatAt(from.Location, from.Map); - - if (boat == null) - { - return; - } - - if (!Active) - { - boat.TillerMan - ?.Say( - 502507 - ); // Ar, Legend has it that these pillars are inactive! No man knows how it might be undone! - - return; - } - - var map = from.Map; - - for (var i = 0; i < 5; i++) // Try 5 times - { - var x = Utility.Random(Destination.X, Destination.Width); - var y = Utility.Random(Destination.Y, Destination.Height); - var z = map.GetAverageZ(x, y); - - var dest = new Point3D(x, y, z); - - if (boat.CanFit(dest, map, boat.ItemID)) - { - var xOffset = x - boat.X; - var yOffset = y - boat.Y; - var zOffset = z - boat.Z; - - boat.Teleport(xOffset, yOffset, zOffset); - - return; - } - } - - boat.TillerMan?.Say(502508); // Ar, I refuse to take that matey through here! + return; } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + if (!Active) + { + // Ar, Legend has it that these pillars are inactive! No man knows how it might be undone! + boat.TillerMan?.Say(502507); + return; + } - writer.WriteEncodedInt(0); // version + var map = from.Map; - writer.Write(Active); - writer.Write(Word); - writer.Write(Destination); - } + for (var i = 0; i < 5; i++) // Try 5 times + { + var x = Utility.Random(Destination.X, Destination.Width); + var y = Utility.Random(Destination.Y, Destination.Height); + var z = map.GetAverageZ(x, y); - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + var dest = new Point3D(x, y, z); - var version = reader.ReadEncodedInt(); + if (boat.CanFit(dest, map, boat.ItemID)) + { + var xOffset = x - boat.X; + var yOffset = y - boat.Y; + var zOffset = z - boat.Z; - Active = reader.ReadBool(); - Word = reader.ReadString(); - Destination = reader.ReadRect2D(); + boat.Teleport(xOffset, yOffset, zOffset); + + return; + } + } + + boat.TillerMan?.Say(502508); // Ar, I refuse to take that matey through here! } } } diff --git a/Projects/UOContent/Items/Misc/SpecialBeardDye.cs b/Projects/UOContent/Items/Misc/SpecialBeardDye.cs index 9ce604fb9..e19aa1abe 100644 --- a/Projects/UOContent/Items/Misc/SpecialBeardDye.cs +++ b/Projects/UOContent/Items/Misc/SpecialBeardDye.cs @@ -1,164 +1,146 @@ +using System; +using ModernUO.Serialization; using Server.Gumps; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class SpecialBeardDye : Item { - public class SpecialBeardDye : Item + [Constructible] + public SpecialBeardDye() : base(0xE26) { - [Constructible] - public SpecialBeardDye() : base(0xE26) - { - Weight = 1.0; - LootType = LootType.Newbied; - } - - public SpecialBeardDye(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041087; // Special Beard Dye - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 1)) - { - from.CloseGump(); - from.SendGump(new SpecialBeardDyeGump(this)); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. - } - } + Weight = 1.0; + LootType = LootType.Newbied; } - public class SpecialBeardDyeGump : Gump + public override int LabelNumber => 1041087; // Special Beard Dye + + public override void OnDoubleClick(Mobile from) { - private static readonly SpecialBeardDyeEntry[] m_Entries = + if (from.InRange(GetWorldLocation(), 1)) { - new("*****", 12, 10), - new("*****", 32, 5), - new("*****", 38, 8), - new("*****", 54, 3), - new("*****", 62, 10), - new("*****", 81, 2), - new("*****", 89, 2), - new("*****", 1153, 2) - }; - - private readonly SpecialBeardDye m_SpecialBeardDye; - - public SpecialBeardDyeGump(SpecialBeardDye dye) : base(0, 0) - { - m_SpecialBeardDye = dye; - - AddPage(0); - AddBackground(150, 60, 350, 358, 2600); - AddBackground(170, 104, 110, 270, 5100); - AddHtmlLocalized(230, 75, 200, 20, 1011013); // Hair Color Selection Menu - AddHtmlLocalized(235, 380, 300, 20, 1013007); // Dye my beard this color! - AddButton(200, 380, 0xFA5, 0xFA7, 1); // DYE HAIR - - for (var i = 0; i < m_Entries.Length; ++i) - { - AddLabel(180, 109 + i * 22, m_Entries[i].HueStart - 1, m_Entries[i].Name); - AddButton(257, 110 + i * 22, 5224, 5224, 0, GumpButtonType.Page, i + 1); - } - - for (var i = 0; i < m_Entries.Length; ++i) - { - var e = m_Entries[i]; - - AddPage(i + 1); - - for (var j = 0; j < e.HueCount; ++j) - { - AddLabel(328 + j / 16 * 80, 102 + j % 16 * 17, e.HueStart + j - 1, "*****"); - AddRadio(310 + j / 16 * 80, 102 + j % 16 * 17, 210, 211, false, i * 100 + j); - } - } + from.CloseGump(); + from.SendGump(new SpecialBeardDyeGump(this)); } - - public override void OnResponse(NetState from, RelayInfo info) + else { - if (m_SpecialBeardDye.Deleted) - { - return; - } - - var m = from.Mobile; - var switches = info.Switches; - - if (!m_SpecialBeardDye.IsChildOf(m.Backpack)) - { - m.SendLocalizedMessage(1042010); // You must have the objectin your backpack to use it. - return; - } - - if (info.ButtonID != 0 && switches.Length > 0) - { - if (m.FacialHairItemID == 0) - { - m.SendLocalizedMessage(502623); // You have no hair to dye and cannot use this - } - else - { - // To prevent this from being exploited, the hue is abstracted into an internal list - - var entryIndex = switches[0] / 100; - var hueOffset = switches[0] % 100; - - if (entryIndex >= 0 && entryIndex < m_Entries.Length) - { - var e = m_Entries[entryIndex]; - - if (hueOffset >= 0 && hueOffset < e.HueCount) - { - var hue = e.HueStart + hueOffset; - - m.FacialHairHue = hue; - - m.SendLocalizedMessage(501199); // You dye your hair - m_SpecialBeardDye.Delete(); - m.PlaySound(0x4E); - } - } - } - } - else - { - m.SendLocalizedMessage(501200); // You decide not to dye your hair - } - } - - private class SpecialBeardDyeEntry - { - public SpecialBeardDyeEntry(string name, int hueStart, int hueCount) - { - Name = name; - HueStart = hueStart; - HueCount = hueCount; - } - - public string Name { get; } - - public int HueStart { get; } - - public int HueCount { get; } + from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. } } } + +public class SpecialBeardDyeGump : Gump +{ + private static SpecialBeardDyeEntry[] _entries = + { + new("*****", 12, 10), + new("*****", 32, 5), + new("*****", 38, 8), + new("*****", 54, 3), + new("*****", 62, 10), + new("*****", 81, 2), + new("*****", 89, 2), + new("*****", 1153, 2) + }; + + private SpecialBeardDye _specialBeardDye; + + public SpecialBeardDyeGump(SpecialBeardDye dye) : base(0, 0) + { + _specialBeardDye = dye; + + AddPage(0); + AddBackground(150, 60, 350, 358, 2600); + AddBackground(170, 104, 110, 270, 5100); + AddHtmlLocalized(230, 75, 200, 20, 1011013); // Hair Color Selection Menu + AddHtmlLocalized(235, 380, 300, 20, 1013007); // Dye my beard this color! + AddButton(200, 380, 0xFA5, 0xFA7, 1); // DYE HAIR + + for (var i = 0; i < _entries.Length; ++i) + { + AddLabel(180, 109 + i * 22, _entries[i].HueStart - 1, _entries[i].Name); + AddButton(257, 110 + i * 22, 5224, 5224, 0, GumpButtonType.Page, i + 1); + } + + for (var i = 0; i < _entries.Length; ++i) + { + var e = _entries[i]; + + AddPage(i + 1); + + for (var j = 0; j < e.HueCount; ++j) + { + AddLabel(328 + j / 16 * 80, 102 + j % 16 * 17, e.HueStart + j - 1, "*****"); + AddRadio(310 + j / 16 * 80, 102 + j % 16 * 17, 210, 211, false, i * 100 + j); + } + } + } + + public override void OnResponse(NetState from, RelayInfo info) + { + if (_specialBeardDye.Deleted) + { + return; + } + + var m = from.Mobile; + var switches = info.Switches; + + if (!_specialBeardDye.IsChildOf(m.Backpack)) + { + m.SendLocalizedMessage(1042010); // You must have the object in your backpack to use it. + return; + } + + if (info.ButtonID != 0 && switches.Length > 0) + { + if (m.FacialHairItemID == 0) + { + m.SendLocalizedMessage(502623); // You have no hair to dye and cannot use this + } + else + { + // To prevent this from being exploited, the hue is abstracted into an internal list + var entryIndex = Math.DivRem(switches[0], 100, out var hueOffset); + + if (entryIndex >= 0 && entryIndex < _entries.Length) + { + var e = _entries[entryIndex]; + + if (hueOffset >= 0 && hueOffset < e.HueCount) + { + var hue = e.HueStart + hueOffset; + + m.FacialHairHue = hue; + + m.SendLocalizedMessage(501199); // You dye your hair + _specialBeardDye.Delete(); + m.PlaySound(0x4E); + } + } + } + } + else + { + m.SendLocalizedMessage(501200); // You decide not to dye your hair + } + } + + private class SpecialBeardDyeEntry + { + public SpecialBeardDyeEntry(string name, int hueStart, int hueCount) + { + Name = name; + HueStart = hueStart; + HueCount = hueCount; + } + + public string Name { get; } + + public int HueStart { get; } + + public int HueCount { get; } + } +} diff --git a/Projects/UOContent/Items/Misc/SpecialHairDye.cs b/Projects/UOContent/Items/Misc/SpecialHairDye.cs index 3829506bd..b7149e7a2 100644 --- a/Projects/UOContent/Items/Misc/SpecialHairDye.cs +++ b/Projects/UOContent/Items/Misc/SpecialHairDye.cs @@ -1,165 +1,147 @@ +using System; +using ModernUO.Serialization; using Server.Gumps; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class SpecialHairDye : Item { - public class SpecialHairDye : Item + [Constructible] + public SpecialHairDye() : base(0xE26) { - [Constructible] - public SpecialHairDye() : base(0xE26) - { - Weight = 1.0; - LootType = LootType.Newbied; - } - - public SpecialHairDye(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Special Hair Dye"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 1)) - { - from.CloseGump(); - from.SendGump(new SpecialHairDyeGump(this)); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. - } - } + Weight = 1.0; + LootType = LootType.Newbied; } - public class SpecialHairDyeGump : Gump + public override int LabelNumber => 1074402; + + public override void OnDoubleClick(Mobile from) { - private static readonly SpecialHairDyeEntry[] m_Entries = + if (from.InRange(GetWorldLocation(), 1)) { - new("*****", 12, 10), - new("*****", 32, 5), - new("*****", 38, 8), - new("*****", 54, 3), - new("*****", 62, 10), - new("*****", 81, 2), - new("*****", 89, 2), - new("*****", 1153, 2) - }; - - private readonly SpecialHairDye m_SpecialHairDye; - - public SpecialHairDyeGump(SpecialHairDye dye) : base(0, 0) - { - m_SpecialHairDye = dye; - - AddPage(0); - AddBackground(150, 60, 350, 358, 2600); - AddBackground(170, 104, 110, 270, 5100); - AddHtmlLocalized(230, 75, 200, 20, 1011013); // Hair Color Selection Menu - AddHtmlLocalized(235, 380, 300, 20, 1011014); // Dye my hair this color! - AddButton(200, 380, 0xFA5, 0xFA7, 1); // DYE HAIR - - for (var i = 0; i < m_Entries.Length; ++i) - { - AddLabel(180, 109 + i * 22, m_Entries[i].HueStart - 1, m_Entries[i].Name); - AddButton(257, 110 + i * 22, 5224, 5224, 0, GumpButtonType.Page, i + 1); - } - - for (var i = 0; i < m_Entries.Length; ++i) - { - var e = m_Entries[i]; - - AddPage(i + 1); - - for (var j = 0; j < e.HueCount; ++j) - { - AddLabel(328 + j / 16 * 80, 102 + j % 16 * 17, e.HueStart + j - 1, "*****"); - AddRadio(310 + j / 16 * 80, 102 + j % 16 * 17, 210, 211, false, i * 100 + j); - } - } + from.CloseGump(); + from.SendGump(new SpecialHairDyeGump(this)); } - - public override void OnResponse(NetState from, RelayInfo info) + else { - if (m_SpecialHairDye.Deleted) - { - return; - } - - var m = from.Mobile; - var switches = info.Switches; - - if (!m_SpecialHairDye.IsChildOf(m.Backpack)) - { - m.SendLocalizedMessage(1042010); // You must have the objectin your backpack to use it. - return; - } - - if (info.ButtonID != 0 && switches.Length > 0) - { - if (m.HairItemID == 0) - { - m.SendLocalizedMessage(502623); // You have no hair to dye and cannot use this - } - else - { - // To prevent this from being exploited, the hue is abstracted into an internal list - - var entryIndex = switches[0] / 100; - var hueOffset = switches[0] % 100; - - if (entryIndex >= 0 && entryIndex < m_Entries.Length) - { - var e = m_Entries[entryIndex]; - - if (hueOffset >= 0 && hueOffset < e.HueCount) - { - m_SpecialHairDye.Delete(); - - var hue = e.HueStart + hueOffset; - - m.HairHue = hue; - - m.SendLocalizedMessage(501199); // You dye your hair - m.PlaySound(0x4E); - } - } - } - } - else - { - m.SendLocalizedMessage(501200); // You decide not to dye your hair - } - } - - private class SpecialHairDyeEntry - { - public SpecialHairDyeEntry(string name, int hueStart, int hueCount) - { - Name = name; - HueStart = hueStart; - HueCount = hueCount; - } - - public string Name { get; } - - public int HueStart { get; } - - public int HueCount { get; } + from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. } } } + +public class SpecialHairDyeGump : Gump +{ + private static readonly SpecialHairDyeEntry[] _entries = + { + new("*****", 12, 10), + new("*****", 32, 5), + new("*****", 38, 8), + new("*****", 54, 3), + new("*****", 62, 10), + new("*****", 81, 2), + new("*****", 89, 2), + new("*****", 1153, 2) + }; + + private SpecialHairDye _specialHairDye; + + public SpecialHairDyeGump(SpecialHairDye dye) : base(0, 0) + { + _specialHairDye = dye; + + AddPage(0); + AddBackground(150, 60, 350, 358, 2600); + AddBackground(170, 104, 110, 270, 5100); + AddHtmlLocalized(230, 75, 200, 20, 1011013); // Hair Color Selection Menu + AddHtmlLocalized(235, 380, 300, 20, 1011014); // Dye my hair this color! + AddButton(200, 380, 0xFA5, 0xFA7, 1); // DYE HAIR + + for (var i = 0; i < _entries.Length; ++i) + { + AddLabel(180, 109 + i * 22, _entries[i].HueStart - 1, _entries[i].Name); + AddButton(257, 110 + i * 22, 5224, 5224, 0, GumpButtonType.Page, i + 1); + } + + for (var i = 0; i < _entries.Length; ++i) + { + var e = _entries[i]; + + AddPage(i + 1); + + for (var j = 0; j < e.HueCount; ++j) + { + AddLabel(328 + j / 16 * 80, 102 + j % 16 * 17, e.HueStart + j - 1, "*****"); + AddRadio(310 + j / 16 * 80, 102 + j % 16 * 17, 210, 211, false, i * 100 + j); + } + } + } + + public override void OnResponse(NetState from, RelayInfo info) + { + if (_specialHairDye.Deleted) + { + return; + } + + var m = from.Mobile; + var switches = info.Switches; + + if (!_specialHairDye.IsChildOf(m.Backpack)) + { + m.SendLocalizedMessage(1042010); // You must have the objecti n your backpack to use it. + return; + } + + if (info.ButtonID != 0 && switches.Length > 0) + { + if (m.HairItemID == 0) + { + m.SendLocalizedMessage(502623); // You have no hair to dye and cannot use this + } + else + { + // To prevent this from being exploited, the hue is abstracted into an internal list + var entryIndex = Math.DivRem(switches[0], 100, out var hueOffset); + + if (entryIndex >= 0 && entryIndex < _entries.Length) + { + var e = _entries[entryIndex]; + + if (hueOffset >= 0 && hueOffset < e.HueCount) + { + _specialHairDye.Delete(); + + var hue = e.HueStart + hueOffset; + + m.HairHue = hue; + + m.SendLocalizedMessage(501199); // You dye your hair + m.PlaySound(0x4E); + } + } + } + } + else + { + m.SendLocalizedMessage(501200); // You decide not to dye your hair + } + } + + private class SpecialHairDyeEntry + { + public SpecialHairDyeEntry(string name, int hueStart, int hueCount) + { + Name = name; + HueStart = hueStart; + HueCount = hueCount; + } + + public string Name { get; } + + public int HueStart { get; } + + public int HueCount { get; } + } +} diff --git a/Projects/UOContent/Items/Misc/Static.cs b/Projects/UOContent/Items/Misc/Static.cs index d7700830d..01d747f5e 100644 --- a/Projects/UOContent/Items/Misc/Static.cs +++ b/Projects/UOContent/Items/Misc/Static.cs @@ -1,92 +1,37 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class Static : Item { - public class Static : Item + public Static() : base(0x80) => Movable = false; + + [Constructible] + public Static(int itemID) : base(itemID) => Movable = false; + + [Constructible] + public Static(int itemID, int count) : this(Utility.Random(itemID, count)) { - public Static() : base(0x80) => Movable = false; - - [Constructible] - public Static(int itemID) : base(itemID) => Movable = false; - - [Constructible] - public Static(int itemID, int count) : this(Utility.Random(itemID, count)) - { - } - - public Static(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (version == 0 && Weight == 0) - { - Weight = -1; - } - } - } - - public class LocalizedStatic : Static - { - private int m_LabelNumber; - - [Constructible] - public LocalizedStatic(int itemID) : this(itemID, itemID < 0x4000 ? 1020000 + itemID : 1078872 + itemID) - { - } - - [Constructible] - public LocalizedStatic(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; - - public LocalizedStatic(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Number - { - get => m_LabelNumber; - set - { - m_LabelNumber = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => m_LabelNumber; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - writer.WriteEncodedInt(m_LabelNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadEncodedInt(); - break; - } - } - } } } + +[SerializationGenerator(0)] +public partial class LocalizedStatic : Static +{ + [EncodedInt] + [InvalidateProperties] + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private int _number; + + [Constructible] + public LocalizedStatic(int itemID) : this(itemID, itemID < 0x4000 ? 1020000 + itemID : 1078872 + itemID) + { + } + + [Constructible] + public LocalizedStatic(int itemID, int number) : base(itemID) => _number = number; + + public override int LabelNumber => _number; +} diff --git a/Projects/UOContent/Items/Misc/SwarmOfFlies.cs b/Projects/UOContent/Items/Misc/SwarmOfFlies.cs index 5bd68c62d..6411fda38 100644 --- a/Projects/UOContent/Items/Misc/SwarmOfFlies.cs +++ b/Projects/UOContent/Items/Misc/SwarmOfFlies.cs @@ -1,32 +1,16 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class SwarmOfFlies : Item { - public class SwarmOfFlies : Item + [Constructible] + public SwarmOfFlies() : base(0x91B) { - [Constructible] - public SwarmOfFlies() : base(0x91B) - { - Hue = 1; - Movable = false; - } - - public SwarmOfFlies(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a swarm of flies"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } + Hue = 1; + Movable = false; } + + public override string DefaultName => "a swarm of flies"; } diff --git a/Projects/UOContent/Items/Misc/Teleporter.cs b/Projects/UOContent/Items/Misc/Teleporter.cs index 07dcb6af0..14d344cde 100644 --- a/Projects/UOContent/Items/Misc/Teleporter.cs +++ b/Projects/UOContent/Items/Misc/Teleporter.cs @@ -1,1284 +1,1093 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.Buffers; using Server.Mobiles; using Server.Network; using Server.Spells; -namespace Server.Items +namespace Server.Items; + +[Flags] +public enum TeleporterFlags { - public class Teleporter : Item + None = 0x00000000, + Active = 0x00000001, + Creatures = 0x00000002, + CombatCheck = 0x00000004, + CriminalCheck = 0x00000008, + SourceEffect = 0x00000010, + DestEffect = 0x00000020 +} + +[SerializationGenerator(5, false)] +public partial class Teleporter : Item +{ + [InvalidateProperties] + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TeleporterFlags _flags; + + [InvalidateProperties] + [SerializableField(1)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TimeSpan _delay; + + [EncodedInt] + [InvalidateProperties] + [SerializableField(2)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private int _soundID; + + [InvalidateProperties] + [SerializableField(3)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private Point3D _pointDest; + + [InvalidateProperties] + [SerializableField(4)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private Map _mapDest; + + [Constructible] + public Teleporter() : this(new Point3D(0, 0, 0)) { - private bool m_Active, m_Creatures, m_CombatCheck, m_CriminalCheck; - private TimeSpan m_Delay; - private bool m_DestEffect; - private Map m_MapDest; - private Point3D m_PointDest; - private int m_SoundID; - private bool m_SourceEffect; + } - [Constructible] - public Teleporter() : this(new Point3D(0, 0, 0)) + [Constructible] + public Teleporter(Point3D pointDest, Map mapDest = null, bool creatures = false) : base(0x1BC3) + { + Movable = false; + Visible = false; + + _flags = TeleporterFlags.Active; + Creatures = creatures; + + _pointDest = pointDest; + _mapDest = mapDest; + } + + public bool GetFlag(TeleporterFlags flag) => (Flags & flag) != 0; + + public void SetFlag(TeleporterFlags flag, bool value) + { + if (value) { + Flags |= flag; + } + else + { + Flags &= ~flag; } - [Constructible] - public Teleporter(Point3D pointDest, Map mapDest = null, bool creatures = false) : base(0x1BC3) + InvalidateProperties(); + this.MarkDirty(); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SourceEffect + { + get => GetFlag(TeleporterFlags.SourceEffect); + set => SetFlag(TeleporterFlags.SourceEffect, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DestEffect + { + get => GetFlag(TeleporterFlags.DestEffect); + set => SetFlag(TeleporterFlags.DestEffect, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active + { + get => GetFlag(TeleporterFlags.Active); + set => SetFlag(TeleporterFlags.Active, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Creatures + { + get => GetFlag(TeleporterFlags.Creatures); + set => SetFlag(TeleporterFlags.Creatures, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool CombatCheck + { + get => GetFlag(TeleporterFlags.CombatCheck); + set => SetFlag(TeleporterFlags.CombatCheck, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool CriminalCheck + { + get => GetFlag(TeleporterFlags.CriminalCheck); + set => SetFlag(TeleporterFlags.CriminalCheck, value); + } + + public override int LabelNumber => 1026095; // teleporter + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + if (Active) { - Movable = false; - Visible = false; - - m_Active = true; - m_PointDest = pointDest; - m_MapDest = mapDest; - m_Creatures = creatures; - - m_CombatCheck = false; - m_CriminalCheck = false; + list.Add(1060742); // active + } + else + { + list.Add(1060743); // inactive } - public Teleporter(Serial serial) : base(serial) + if (_mapDest != null) { + list.Add(1060658, $"{"Map"}\t{_mapDest}"); } - [CommandProperty(AccessLevel.GameMaster)] - public bool SourceEffect + if (_pointDest != Point3D.Zero) { - get => m_SourceEffect; - set - { - m_SourceEffect = value; - InvalidateProperties(); - } + list.Add(1060659, $"{"Coords"}\t{_pointDest}"); } - [CommandProperty(AccessLevel.GameMaster)] - public bool DestEffect + list.Add(1060660, $"{"Creatures"}\t{(Creatures ? "Yes" : "No")}"); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (Active) { - get => m_DestEffect; - set + if (_mapDest != null && _pointDest != Point3D.Zero) { - m_DestEffect = value; - InvalidateProperties(); + LabelTo(from, "{0} [{1}]", _pointDest, _mapDest); + } + else if (_mapDest != null) + { + LabelTo(from, "[{0}]", _mapDest); + } + else if (_pointDest != Point3D.Zero) + { + LabelTo(from, _pointDest.ToString()); } } - - [CommandProperty(AccessLevel.GameMaster)] - public int SoundID + else { - get => m_SoundID; - set - { - m_SoundID = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan Delay - { - get => m_Delay; - set - { - m_Delay = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active - { - get => m_Active; - set - { - m_Active = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D PointDest - { - get => m_PointDest; - set - { - m_PointDest = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Map MapDest - { - get => m_MapDest; - set - { - m_MapDest = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Creatures - { - get => m_Creatures; - set - { - m_Creatures = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool CombatCheck - { - get => m_CombatCheck; - set - { - m_CombatCheck = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool CriminalCheck - { - get => m_CriminalCheck; - set - { - m_CriminalCheck = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1026095; // teleporter - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - if (m_Active) - { - list.Add(1060742); // active - } - else - { - list.Add(1060743); // inactive - } - - if (m_MapDest != null) - { - list.Add(1060658, $"{"Map"}\t{m_MapDest}"); - } - - if (m_PointDest != Point3D.Zero) - { - list.Add(1060659, $"{"Coords"}\t{m_PointDest}"); - } - - list.Add(1060660, $"{"Creatures"}\t{(m_Creatures ? "Yes" : "No")}"); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (m_Active) - { - if (m_MapDest != null && m_PointDest != Point3D.Zero) - { - LabelTo(from, "{0} [{1}]", m_PointDest, m_MapDest); - } - else if (m_MapDest != null) - { - LabelTo(from, "[{0}]", m_MapDest); - } - else if (m_PointDest != Point3D.Zero) - { - LabelTo(from, m_PointDest.ToString()); - } - } - else - { - LabelTo(from, "(inactive)"); - } - } - - public virtual bool CanTeleport(Mobile m) - { - if (!m_Creatures && !m.Player) - { - return false; - } - - if (m_CriminalCheck && m.Criminal) - { - m.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - return false; - } - - if (m_CombatCheck && SpellHelper.CheckCombat(m)) - { - m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - return false; - } - - return true; - } - - public virtual void StartTeleport(Mobile m) - { - if (m_Delay == TimeSpan.Zero) - { - DoTeleport(m); - } - else - { - Timer.StartTimer(m_Delay, () => DoTeleport(m)); - } - } - - public virtual void DoTeleport(Mobile m) - { - var map = m_MapDest; - - if (map == null || map == Map.Internal) - { - map = m.Map; - } - - var p = m_PointDest; - - if (p == Point3D.Zero) - { - p = m.Location; - } - - BaseCreature.TeleportPets(m, p, map); - - var sendEffect = !m.Hidden || m.AccessLevel == AccessLevel.Player; - - if (m_SourceEffect && sendEffect) - { - Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10); - } - - m.MoveToWorld(p, map); - - if (m_DestEffect && sendEffect) - { - Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10); - } - - if (m_SoundID > 0 && sendEffect) - { - Effects.PlaySound(m.Location, m.Map, m_SoundID); - } - } - - public override bool OnMoveOver(Mobile m) - { - if (m_Active && CanTeleport(m)) - { - StartTeleport(m); - return false; - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(4); // version - - writer.Write(m_CriminalCheck); - writer.Write(m_CombatCheck); - - writer.Write(m_SourceEffect); - writer.Write(m_DestEffect); - writer.Write(m_Delay); - writer.WriteEncodedInt(m_SoundID); - - writer.Write(m_Creatures); - - writer.Write(m_Active); - writer.Write(m_PointDest); - writer.Write(m_MapDest); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 4: - { - m_CriminalCheck = reader.ReadBool(); - goto case 3; - } - case 3: - { - m_CombatCheck = reader.ReadBool(); - goto case 2; - } - case 2: - { - m_SourceEffect = reader.ReadBool(); - m_DestEffect = reader.ReadBool(); - m_Delay = reader.ReadTimeSpan(); - m_SoundID = reader.ReadEncodedInt(); - - goto case 1; - } - case 1: - { - m_Creatures = reader.ReadBool(); - - goto case 0; - } - case 0: - { - m_Active = reader.ReadBool(); - m_PointDest = reader.ReadPoint3D(); - m_MapDest = reader.ReadMap(); - - break; - } - } + LabelTo(from, "(inactive)"); } } - public class SkillTeleporter : Teleporter + public virtual bool CanTeleport(Mobile m) { - private int m_MessageNumber; - private string m_MessageString; - private double m_Required; - private SkillName m_Skill; - - [Constructible] - public SkillTeleporter() + if (!Creatures && !m.Player) { + return false; } - public SkillTeleporter(Serial serial) - : base(serial) + if (CriminalCheck && m.Criminal) { + m.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + return false; } - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill + if (CombatCheck && SpellHelper.CheckCombat(m)) { - get => m_Skill; - set - { - m_Skill = value; - InvalidateProperties(); - } + m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + return false; } - [CommandProperty(AccessLevel.GameMaster)] - public double Required + return true; + } + + public virtual void StartTeleport(Mobile m) + { + if (_delay == TimeSpan.Zero) { - get => m_Required; - set - { - m_Required = value; - InvalidateProperties(); - } + DoTeleport(m); } - - [CommandProperty(AccessLevel.GameMaster)] - public string MessageString + else { - get => m_MessageString; - set - { - m_MessageString = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MessageNumber - { - get => m_MessageNumber; - set - { - m_MessageNumber = value; - InvalidateProperties(); - } - } - - public override bool CanTeleport(Mobile m) - { - if (!base.CanTeleport(m)) - { - return false; - } - - var sk = m.Skills[m_Skill]; - - if (sk == null || sk.Base < m_Required) - { - if (m.BeginAction(this)) - { - if (m_MessageString != null) - { - m.NetState.SendMessage( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - false, - "ENU", - null, - m_MessageString - ); - } - else if (m_MessageNumber != 0) - { - m.NetState.SendMessageLocalized( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - m_MessageNumber, - null - ); - } - - Timer.StartTimer(TimeSpan.FromSeconds(5.0), () => m.EndAction(this)); - } - - return false; - } - - return true; - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - var skillIndex = (int)m_Skill; - string skillName; - - if (skillIndex >= 0 && skillIndex < SkillInfo.Table.Length) - { - skillName = SkillInfo.Table[skillIndex].Name; - } - else - { - skillName = "(Invalid)"; - } - - list.Add(1060661, $"{skillName}\t{m_Required:F1}"); - - if (m_MessageString != null) - { - list.Add(1060662, $"{"Message"}\t{m_MessageString}"); - } - else if (m_MessageNumber != 0) - { - list.Add(1060662, $"{"Message"}\t{m_MessageNumber:#}"); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Skill); - writer.Write(m_Required); - writer.Write(m_MessageString); - writer.Write(m_MessageNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Skill = (SkillName)reader.ReadInt(); - m_Required = reader.ReadDouble(); - m_MessageString = reader.ReadString(); - m_MessageNumber = reader.ReadInt(); - - break; - } - } + Timer.StartTimer(_delay, () => DoTeleport(m)); } } - public class KeywordTeleporter : Teleporter + public virtual void DoTeleport(Mobile m) { - private int m_Keyword; - private int m_Range; - private string m_Substring; + var map = _mapDest; - [Constructible] - public KeywordTeleporter() + if (map == null || map == Map.Internal) { - m_Keyword = -1; - m_Substring = null; + map = m.Map; } - public KeywordTeleporter(Serial serial) - : base(serial) + var p = _pointDest; + + if (p == Point3D.Zero) { + p = m.Location; } - [CommandProperty(AccessLevel.GameMaster)] - public string Substring + BaseCreature.TeleportPets(m, p, map); + + var sendEffect = !m.Hidden || m.AccessLevel == AccessLevel.Player; + + if (SourceEffect && sendEffect) { - get => m_Substring; - set - { - m_Substring = value; - InvalidateProperties(); - } + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10); } - [CommandProperty(AccessLevel.GameMaster)] - public int Keyword + m.MoveToWorld(p, map); + + if (DestEffect && sendEffect) { - get => m_Keyword; - set - { - m_Keyword = value; - InvalidateProperties(); - } + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10); } - [CommandProperty(AccessLevel.GameMaster)] - public int Range + if (_soundID > 0 && sendEffect) { - get => m_Range; - set - { - m_Range = value; - InvalidateProperties(); - } + Effects.PlaySound(m.Location, m.Map, _soundID); + } + } + + public override bool OnMoveOver(Mobile m) + { + if (Active && CanTeleport(m)) + { + StartTeleport(m); + return false; } - public override bool HandlesOnSpeech => true; + return true; + } - public override void OnSpeech(SpeechEventArgs e) + private void Deserialize(IGenericReader reader, int version) + { + if (reader.ReadBool()) { - if (!e.Handled && Active) - { - var m = e.Mobile; - - if (!m.InRange(GetWorldLocation(), m_Range)) - { - return; - } - - var isMatch = false; - - if (m_Keyword >= 0 && e.HasKeyword(m_Keyword)) - { - isMatch = true; - } - else if (m_Substring != null && e.Speech.InsensitiveContains(m_Substring)) - { - isMatch = true; - } - - if (!isMatch || !CanTeleport(m)) - { - return; - } - - e.Handled = true; - StartTeleport(m); - } + _flags |= TeleporterFlags.CriminalCheck; } - public override void DoTeleport(Mobile m) + if (reader.ReadBool()) { - if (!m.InRange(GetWorldLocation(), m_Range) || m.Map != Map) + _flags |= TeleporterFlags.CombatCheck; + } + + if (reader.ReadBool()) + { + _flags |= TeleporterFlags.SourceEffect; + } + + if (reader.ReadBool()) + { + _flags |= TeleporterFlags.DestEffect; + } + + _delay = reader.ReadTimeSpan(); + _soundID = reader.ReadEncodedInt(); + + if (reader.ReadBool()) + { + _flags |= TeleporterFlags.Creatures; + } + + if (reader.ReadBool()) + { + _flags |= TeleporterFlags.Active; + } + + _pointDest = reader.ReadPoint3D(); + _mapDest = reader.ReadMap(); + } +} + +[SerializationGenerator(1, false)] +public partial class SkillTeleporter : Teleporter +{ + [InvalidateProperties] + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private SkillName _skill; + + [InvalidateProperties] + [SerializableField(1)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private double _required; + + [CanBeNull] + [InvalidateProperties] + [SerializableField(2)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TextDefinition _message; + + [Constructible] + public SkillTeleporter() + { + } + + public override bool CanTeleport(Mobile m) + { + if (!base.CanTeleport(m)) + { + return false; + } + + var sk = m.Skills[_skill]; + + if (sk?.Base >= _required) + { + return true; + } + + if (!m.BeginAction(this)) + { + return false; + } + + if (_message?.Number > 0) + { + m.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + _message.Number, + null + ); + } + else if (!string.IsNullOrWhiteSpace(_message?.String)) + { + m.NetState.SendMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + false, + "ENU", + null, + _message.String + ); + } + + Timer.StartTimer(TimeSpan.FromSeconds(5.0), () => m.EndAction(this)); + + return false; + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + var skillIndex = (int)_skill; + string skillName; + + if (skillIndex >= 0 && skillIndex < SkillInfo.Table.Length) + { + skillName = SkillInfo.Table[skillIndex].Name; + } + else + { + skillName = "(Invalid)"; + } + + list.Add(1060661, $"{skillName}\t{_required:F1}"); + + if (_message?.Number > 0) + { + list.Add(1060662, $"{"Message"}\t{_message.Number:#}"); + } + else if (!string.IsNullOrWhiteSpace(_message?.String)) + { + list.Add(1060662, $"{"Message"}\t{_message.String}"); + } + } + + private void Deserialize(IGenericReader reader, int version) + { + _skill = (SkillName)reader.ReadInt(); + _required = reader.ReadDouble(); + _message = reader.ReadString(); + + var localNumber = reader.ReadInt(); + if (localNumber > 0) + { + _message = localNumber; + } + } +} + +[SerializationGenerator(0, false)] +public partial class KeywordTeleporter : Teleporter +{ + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private string _substring; + + [SerializableField(1)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private int _keyword; + + [SerializableField(2)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private int _range; + + [Constructible] + public KeywordTeleporter() + { + _keyword = -1; + _substring = null; + } + + public override bool HandlesOnSpeech => true; + + public override void OnSpeech(SpeechEventArgs e) + { + if (!e.Handled && Active) + { + var m = e.Mobile; + + if (!m.InRange(GetWorldLocation(), _range)) { return; } - base.DoTeleport(m); - } + var isMatch = false; - public override bool OnMoveOver(Mobile m) => true; - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - list.Add(1060661, $"{"Range"}\t{m_Range}"); - - if (m_Keyword >= 0) + if (_keyword >= 0 && e.HasKeyword(_keyword)) { - list.Add(1060662, $"{"Keyword"}\t{m_Keyword}"); + isMatch = true; + } + else if (_substring != null && e.Speech.InsensitiveContains(_substring)) + { + isMatch = true; } - if (m_Substring != null) + if (!isMatch || !CanTeleport(m)) { - list.Add(1060663, $"{"Substring"}\t{m_Substring}"); + return; } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Substring); - writer.Write(m_Keyword); - writer.Write(m_Range); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Substring = reader.ReadString(); - m_Keyword = reader.ReadInt(); - m_Range = reader.ReadInt(); - - break; - } - } + e.Handled = true; + StartTeleport(m); } } - public class WaitTeleporter : KeywordTeleporter + public override void DoTeleport(Mobile m) { - private static Dictionary m_Table = new Dictionary(); - - [Constructible] - public WaitTeleporter() + if (!m.InRange(GetWorldLocation(), _range) || m.Map != Map) { + return; } - public WaitTeleporter(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int StartNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string StartMessage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ProgressNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string ProgressMessage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowTimeRemaining { get; set; } - - public static void Initialize() - { - EventSink.Logout += EventSink_Logout; - } - - public static void EventSink_Logout(Mobile from) - { - if (from != null && m_Table.Remove(from, out var info)) - { - info.TimerToken.Cancel(); - } - } - - public static string FormatTime(TimeSpan ts) - { - if (ts.TotalHours >= 1) - { - var h = (int)Math.Round(ts.TotalHours); - return $"{h} hour{(h == 1 ? "" : "s")}"; - } - - if (ts.TotalMinutes >= 1) - { - var m = (int)Math.Round(ts.TotalMinutes); - return $"{m} minute{(m == 1 ? "" : "s")}"; - } - - var s = Math.Max((int)Math.Round(ts.TotalSeconds), 0); - return $"{s} second{(s == 1 ? "" : "s")}"; - } - - public override void StartTeleport(Mobile m) - { - if (m_Table.TryGetValue(m, out var info)) - { - if (info.Teleporter == this) - { - if (m.BeginAction(this)) - { - if (ProgressMessage != null) - { - m.SendMessage(ProgressMessage); - } - else if (ProgressNumber != 0) - { - m.SendLocalizedMessage(ProgressNumber); - } - - if (ShowTimeRemaining) - { - m.SendMessage("Time remaining: {0}", FormatTime(info.TimerToken.Next - Core.Now)); - } - - Timer.StartTimer(TimeSpan.FromSeconds(5), () => m.EndAction(this)); - } - - return; - } - - info.TimerToken.Cancel(); - } - - if (StartMessage != null) - { - m.SendMessage(StartMessage); - } - else if (StartNumber != 0) - { - m.SendLocalizedMessage(StartNumber); - } - - if (Delay == TimeSpan.Zero) - { - DoTeleport(m); - } - else - { - Timer.StartTimer(Delay, () => DoTeleport(m), out var timerToken); - m_Table[m] = new TeleportingInfo(this, timerToken); - } - } - - public override void DoTeleport(Mobile m) - { - m_Table.Remove(m); - - base.DoTeleport(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(StartNumber); - writer.Write(StartMessage); - writer.Write(ProgressNumber); - writer.Write(ProgressMessage); - writer.Write(ShowTimeRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - StartNumber = reader.ReadInt(); - StartMessage = reader.ReadString(); - ProgressNumber = reader.ReadInt(); - ProgressMessage = reader.ReadString(); - ShowTimeRemaining = reader.ReadBool(); - } - - private class TeleportingInfo - { - public TeleportingInfo(WaitTeleporter tele, TimerExecutionToken token) - { - Teleporter = tele; - TimerToken = token; - } - - public WaitTeleporter Teleporter { get; } - - public TimerExecutionToken TimerToken { get; } - } + base.DoTeleport(m); } - public class TimeoutTeleporter : Teleporter + public override bool OnMoveOver(Mobile m) => true; + + public override void GetProperties(IPropertyList list) { - private Dictionary m_Teleporting; + base.GetProperties(list); - [Constructible] - public TimeoutTeleporter() : this(new Point3D(0, 0, 0)) + list.Add(1060661, $"{"Range"}\t{_range}"); + + if (_keyword >= 0) { + list.Add(1060662, $"{"Keyword"}\t{_keyword}"); } - [Constructible] - public TimeoutTeleporter(Point3D pointDest, Map mapDest = null, bool creatures = false) - : base(pointDest, mapDest, creatures) => - m_Teleporting = new Dictionary(); - - public TimeoutTeleporter(Serial serial) - : base(serial) + if (_substring != null) { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan TimeoutDelay { get; set; } - - public void StartTimer(Mobile m) - { - StartTimer(m, TimeoutDelay); - } - - private void StartTimer(Mobile m, TimeSpan delay) - { - StopTimer(m); - Timer.StartTimer(delay, () => StartTeleport(m), out var timerToken); - m_Teleporting[m] = timerToken; - } - - public void StopTimer(Mobile m) - { - if (m_Teleporting.Remove(m, out var t)) - { - t.Cancel(); - } - } - - public override void DoTeleport(Mobile m) - { - m_Teleporting.Remove(m); - - base.DoTeleport(m); - } - - public override bool OnMoveOver(Mobile m) - { - if (Active) - { - if (!CanTeleport(m)) - { - return false; - } - - StartTimer(m); - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(TimeoutDelay); - writer.Write(m_Teleporting.Count); - - foreach (var kvp in m_Teleporting) - { - writer.Write(kvp.Key); - writer.Write(kvp.Value.Next); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - TimeoutDelay = reader.ReadTimeSpan(); - m_Teleporting = new Dictionary(); - - var count = reader.ReadInt(); - - for (var i = 0; i < count; ++i) - { - var m = reader.ReadEntity(); - var end = reader.ReadDateTime(); - - StartTimer(m, end - Core.Now); - } - } - } - - public class TimeoutGoal : Item - { - [Constructible] - public TimeoutGoal() - : base(0x1822) - { - Movable = false; - Visible = false; - - Hue = 1154; - } - - public TimeoutGoal(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeoutTeleporter Teleporter { get; set; } - - public override string DefaultName => "timeout teleporter goal"; - - public override bool OnMoveOver(Mobile m) - { - Teleporter?.StopTimer(m); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Teleporter); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - Teleporter = reader.ReadEntity(); - } - } - - public class ConditionTeleporter : Teleporter - { - private ConditionFlag m_Flags; - - [Constructible] - public ConditionTeleporter() - { - } - - public ConditionTeleporter(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyMounted - { - get => GetFlag(ConditionFlag.DenyMounted); - set - { - SetFlag(ConditionFlag.DenyMounted, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyFollowers - { - get => GetFlag(ConditionFlag.DenyFollowers); - set - { - SetFlag(ConditionFlag.DenyFollowers, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyPackContents - { - get => GetFlag(ConditionFlag.DenyPackContents); - set - { - SetFlag(ConditionFlag.DenyPackContents, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyHolding - { - get => GetFlag(ConditionFlag.DenyHolding); - set - { - SetFlag(ConditionFlag.DenyHolding, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyEquipment - { - get => GetFlag(ConditionFlag.DenyEquipment); - set - { - SetFlag(ConditionFlag.DenyEquipment, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyTransformed - { - get => GetFlag(ConditionFlag.DenyTransformed); - set - { - SetFlag(ConditionFlag.DenyTransformed, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool StaffOnly - { - get => GetFlag(ConditionFlag.StaffOnly); - set - { - SetFlag(ConditionFlag.StaffOnly, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DenyPackEthereals - { - get => GetFlag(ConditionFlag.DenyPackEthereals); - set - { - SetFlag(ConditionFlag.DenyPackEthereals, value); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DeadOnly - { - get => GetFlag(ConditionFlag.DeadOnly); - set - { - SetFlag(ConditionFlag.DeadOnly, value); - InvalidateProperties(); - } - } - - public override bool CanTeleport(Mobile m) - { - if (!base.CanTeleport(m)) - { - return false; - } - - if (GetFlag(ConditionFlag.StaffOnly) && m.AccessLevel < AccessLevel.Counselor) - { - return false; - } - - if (GetFlag(ConditionFlag.DenyMounted) && m.Mounted) - { - m.SendLocalizedMessage(1077252); // You must dismount before proceeding. - return false; - } - - if (GetFlag(ConditionFlag.DenyFollowers) && - (m.Followers != 0 || m is PlayerMobile mobile && mobile.AutoStabled.Count != 0)) - { - m.SendLocalizedMessage(1077250); // No pets permitted beyond this point. - return false; - } - - var pack = m.Backpack; - - if (pack != null) - { - if (GetFlag(ConditionFlag.DenyPackContents) && pack.TotalItems != 0) - { - m.SendMessage("You must empty your backpack before proceeding."); - return false; - } - - if (GetFlag(ConditionFlag.DenyPackEthereals) && - pack.FindItemByType(new[] { typeof(EtherealMount), typeof(BaseImprisonedMobile) }) != null) - { - m.SendMessage("You must empty your backpack of ethereal mounts before proceeding."); - return false; - } - } - - if (GetFlag(ConditionFlag.DenyHolding) && m.Holding != null) - { - m.SendMessage("You must let go of what you are holding before proceeding."); - return false; - } - - if (GetFlag(ConditionFlag.DenyEquipment)) - { - foreach (var item in m.Items) - { - switch (item.Layer) - { - case Layer.Hair: - case Layer.FacialHair: - case Layer.Backpack: - case Layer.Mount: - case Layer.Bank: - { - continue; // ignore - } - default: - { - m.SendMessage("You must remove all of your equipment before proceeding."); - return false; - } - } - } - } - - if (GetFlag(ConditionFlag.DenyTransformed) && m.IsBodyMod) - { - m.SendMessage("You cannot go there in this form."); - return false; - } - - if (GetFlag(ConditionFlag.DeadOnly) && m.Alive) - { - m.SendLocalizedMessage(1060014); // Only the dead may pass. - return false; - } - - return true; - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - using var props = new ValueStringBuilder(stackalloc char[128]); - - if (GetFlag(ConditionFlag.DenyMounted)) - { - props.Append("
Deny Mounted"); - } - - if (GetFlag(ConditionFlag.DenyFollowers)) - { - props.Append("
Deny Followers"); - } - - if (GetFlag(ConditionFlag.DenyPackContents)) - { - props.Append("
Deny Pack Contents"); - } - - if (GetFlag(ConditionFlag.DenyPackEthereals)) - { - props.Append("
Deny Pack Ethereals"); - } - - if (GetFlag(ConditionFlag.DenyHolding)) - { - props.Append("
Deny Holding"); - } - - if (GetFlag(ConditionFlag.DenyEquipment)) - { - props.Append("
Deny Equipment"); - } - - if (GetFlag(ConditionFlag.DenyTransformed)) - { - props.Append("
Deny Transformed"); - } - - if (GetFlag(ConditionFlag.StaffOnly)) - { - props.Append("
Staff Only"); - } - - if (GetFlag(ConditionFlag.DeadOnly)) - { - props.Append("
Dead Only"); - } - - if (props.Length != 0) - { - props.Remove(0, 4); - list.Add(props.ToString()); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Flags); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - m_Flags = (ConditionFlag)reader.ReadInt(); - } - - protected bool GetFlag(ConditionFlag flag) => (m_Flags & flag) != 0; - - protected void SetFlag(ConditionFlag flag, bool value) - { - if (value) - { - m_Flags |= flag; - } - else - { - m_Flags &= ~flag; - } - } - - [Flags] - protected enum ConditionFlag - { - None = 0x000, - DenyMounted = 0x001, - DenyFollowers = 0x002, - DenyPackContents = 0x004, - DenyHolding = 0x008, - DenyEquipment = 0x010, - DenyTransformed = 0x020, - StaffOnly = 0x040, - DenyPackEthereals = 0x080, - DeadOnly = 0x100 + list.Add(1060663, $"{"Substring"}\t{_substring}"); } } } + +[SerializationGenerator(1, false)] +public partial class WaitTeleporter : KeywordTeleporter +{ + private static Dictionary _table = new(); + + [CanBeNull] + [InvalidateProperties] + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TextDefinition _startMessage; + + [CanBeNull] + [InvalidateProperties] + [SerializableField(1)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TextDefinition _progressMessage; + + [InvalidateProperties] + [SerializableField(2)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private bool _showTimeRemaining; + + [Constructible] + public WaitTeleporter() + { + } + + public static void Initialize() + { + EventSink.Logout += EventSink_Logout; + } + + public static void EventSink_Logout(Mobile from) + { + if (from != null && _table.Remove(from, out var info)) + { + info.TimerToken.Cancel(); + } + } + + public static string FormatTime(TimeSpan ts) + { + if (ts.TotalHours >= 1) + { + var h = (int)Math.Round(ts.TotalHours); + return $"{h} hour{(h == 1 ? "" : "s")}"; + } + + if (ts.TotalMinutes >= 1) + { + var m = (int)Math.Round(ts.TotalMinutes); + return $"{m} minute{(m == 1 ? "" : "s")}"; + } + + var s = Math.Max((int)Math.Round(ts.TotalSeconds), 0); + return $"{s} second{(s == 1 ? "" : "s")}"; + } + + public override void StartTeleport(Mobile m) + { + if (_table.TryGetValue(m, out var info)) + { + if (info.Teleporter == this) + { + if (!m.BeginAction(this)) + { + return; + } + + _progressMessage.SendMessageTo(m); + + if (_showTimeRemaining) + { + m.SendMessage($"Time remaining: {FormatTime(info.TimerToken.Next - Core.Now)}"); + } + + Timer.StartTimer(TimeSpan.FromSeconds(5), () => m.EndAction(this)); + + return; + } + + info.TimerToken.Cancel(); + } + + _startMessage.SendMessageTo(m); + + if (Delay == TimeSpan.Zero) + { + DoTeleport(m); + } + else + { + Timer.StartTimer(Delay, () => DoTeleport(m), out var timerToken); + _table[m] = new TeleportingInfo(this, timerToken); + } + } + + public override void DoTeleport(Mobile m) + { + _table.Remove(m); + + base.DoTeleport(m); + } + + private void Deserialize(IGenericReader reader, int version) + { + var number = reader.ReadInt(); + var message = reader.ReadString(); + + _startMessage = number > 0 ? number : message; + + number = reader.ReadInt(); + message = reader.ReadString(); + + _progressMessage = number > 0 ? number : message; + + _showTimeRemaining = reader.ReadBool(); + } + + private class TeleportingInfo + { + public TeleportingInfo(WaitTeleporter tele, TimerExecutionToken token) + { + Teleporter = tele; + TimerToken = token; + } + + public WaitTeleporter Teleporter { get; } + + public TimerExecutionToken TimerToken { get; } + } +} + +public class TimeoutTeleporter : Teleporter +{ + private Dictionary m_Teleporting; + + [Constructible] + public TimeoutTeleporter() : this(new Point3D(0, 0, 0)) + { + } + + [Constructible] + public TimeoutTeleporter(Point3D pointDest, Map mapDest = null, bool creatures = false) + : base(pointDest, mapDest, creatures) => + m_Teleporting = new Dictionary(); + + public TimeoutTeleporter(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan TimeoutDelay { get; set; } + + public void StartTimer(Mobile m) + { + StartTimer(m, TimeoutDelay); + } + + private void StartTimer(Mobile m, TimeSpan delay) + { + StopTimer(m); + Timer.StartTimer(delay, () => StartTeleport(m), out var timerToken); + m_Teleporting[m] = timerToken; + } + + public void StopTimer(Mobile m) + { + if (m_Teleporting.Remove(m, out var t)) + { + t.Cancel(); + } + } + + public override void DoTeleport(Mobile m) + { + m_Teleporting.Remove(m); + + base.DoTeleport(m); + } + + public override bool OnMoveOver(Mobile m) + { + if (Active) + { + if (!CanTeleport(m)) + { + return false; + } + + StartTimer(m); + } + + return true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(TimeoutDelay); + writer.Write(m_Teleporting.Count); + + foreach (var kvp in m_Teleporting) + { + writer.Write(kvp.Key); + writer.Write(kvp.Value.Next); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + TimeoutDelay = reader.ReadTimeSpan(); + m_Teleporting = new Dictionary(); + + var count = reader.ReadInt(); + + for (var i = 0; i < count; ++i) + { + var m = reader.ReadEntity(); + var end = reader.ReadDateTime(); + + StartTimer(m, end - Core.Now); + } + } +} + +public class TimeoutGoal : Item +{ + [Constructible] + public TimeoutGoal() + : base(0x1822) + { + Movable = false; + Visible = false; + + Hue = 1154; + } + + public TimeoutGoal(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeoutTeleporter Teleporter { get; set; } + + public override string DefaultName => "timeout teleporter goal"; + + public override bool OnMoveOver(Mobile m) + { + Teleporter?.StopTimer(m); + + return true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Teleporter); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Teleporter = reader.ReadEntity(); + } +} + +public class ConditionTeleporter : Teleporter +{ + private ConditionFlag m_Flags; + + [Constructible] + public ConditionTeleporter() + { + } + + public ConditionTeleporter(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyMounted + { + get => GetFlag(ConditionFlag.DenyMounted); + set + { + SetFlag(ConditionFlag.DenyMounted, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyFollowers + { + get => GetFlag(ConditionFlag.DenyFollowers); + set + { + SetFlag(ConditionFlag.DenyFollowers, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyPackContents + { + get => GetFlag(ConditionFlag.DenyPackContents); + set + { + SetFlag(ConditionFlag.DenyPackContents, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyHolding + { + get => GetFlag(ConditionFlag.DenyHolding); + set + { + SetFlag(ConditionFlag.DenyHolding, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyEquipment + { + get => GetFlag(ConditionFlag.DenyEquipment); + set + { + SetFlag(ConditionFlag.DenyEquipment, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyTransformed + { + get => GetFlag(ConditionFlag.DenyTransformed); + set + { + SetFlag(ConditionFlag.DenyTransformed, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool StaffOnly + { + get => GetFlag(ConditionFlag.StaffOnly); + set + { + SetFlag(ConditionFlag.StaffOnly, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DenyPackEthereals + { + get => GetFlag(ConditionFlag.DenyPackEthereals); + set + { + SetFlag(ConditionFlag.DenyPackEthereals, value); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DeadOnly + { + get => GetFlag(ConditionFlag.DeadOnly); + set + { + SetFlag(ConditionFlag.DeadOnly, value); + InvalidateProperties(); + } + } + + public override bool CanTeleport(Mobile m) + { + if (!base.CanTeleport(m)) + { + return false; + } + + if (GetFlag(ConditionFlag.StaffOnly) && m.AccessLevel < AccessLevel.Counselor) + { + return false; + } + + if (GetFlag(ConditionFlag.DenyMounted) && m.Mounted) + { + m.SendLocalizedMessage(1077252); // You must dismount before proceeding. + return false; + } + + if (GetFlag(ConditionFlag.DenyFollowers) && + (m.Followers != 0 || m is PlayerMobile mobile && mobile.AutoStabled.Count != 0)) + { + m.SendLocalizedMessage(1077250); // No pets permitted beyond this point. + return false; + } + + var pack = m.Backpack; + + if (pack != null) + { + if (GetFlag(ConditionFlag.DenyPackContents) && pack.TotalItems != 0) + { + m.SendMessage("You must empty your backpack before proceeding."); + return false; + } + + if (GetFlag(ConditionFlag.DenyPackEthereals) && + pack.FindItemByType(new[] { typeof(EtherealMount), typeof(BaseImprisonedMobile) }) != null) + { + m.SendMessage("You must empty your backpack of ethereal mounts before proceeding."); + return false; + } + } + + if (GetFlag(ConditionFlag.DenyHolding) && m.Holding != null) + { + m.SendMessage("You must let go of what you are holding before proceeding."); + return false; + } + + if (GetFlag(ConditionFlag.DenyEquipment)) + { + foreach (var item in m.Items) + { + switch (item.Layer) + { + case Layer.Hair: + case Layer.FacialHair: + case Layer.Backpack: + case Layer.Mount: + case Layer.Bank: + { + continue; // ignore + } + default: + { + m.SendMessage("You must remove all of your equipment before proceeding."); + return false; + } + } + } + } + + if (GetFlag(ConditionFlag.DenyTransformed) && m.IsBodyMod) + { + m.SendMessage("You cannot go there in this form."); + return false; + } + + if (GetFlag(ConditionFlag.DeadOnly) && m.Alive) + { + m.SendLocalizedMessage(1060014); // Only the dead may pass. + return false; + } + + return true; + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + using var props = new ValueStringBuilder(stackalloc char[128]); + + if (GetFlag(ConditionFlag.DenyMounted)) + { + props.Append("
Deny Mounted"); + } + + if (GetFlag(ConditionFlag.DenyFollowers)) + { + props.Append("
Deny Followers"); + } + + if (GetFlag(ConditionFlag.DenyPackContents)) + { + props.Append("
Deny Pack Contents"); + } + + if (GetFlag(ConditionFlag.DenyPackEthereals)) + { + props.Append("
Deny Pack Ethereals"); + } + + if (GetFlag(ConditionFlag.DenyHolding)) + { + props.Append("
Deny Holding"); + } + + if (GetFlag(ConditionFlag.DenyEquipment)) + { + props.Append("
Deny Equipment"); + } + + if (GetFlag(ConditionFlag.DenyTransformed)) + { + props.Append("
Deny Transformed"); + } + + if (GetFlag(ConditionFlag.StaffOnly)) + { + props.Append("
Staff Only"); + } + + if (GetFlag(ConditionFlag.DeadOnly)) + { + props.Append("
Dead Only"); + } + + if (props.Length != 0) + { + props.Remove(0, 4); + list.Add(props.ToString()); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Flags); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Flags = (ConditionFlag)reader.ReadInt(); + } + + protected bool GetFlag(ConditionFlag flag) => (m_Flags & flag) != 0; + + protected void SetFlag(ConditionFlag flag, bool value) + { + if (value) + { + m_Flags |= flag; + } + else + { + m_Flags &= ~flag; + } + } + + [Flags] + protected enum ConditionFlag + { + None = 0x000, + DenyMounted = 0x001, + DenyFollowers = 0x002, + DenyPackContents = 0x004, + DenyHolding = 0x008, + DenyEquipment = 0x010, + DenyTransformed = 0x020, + StaffOnly = 0x040, + DenyPackEthereals = 0x080, + DeadOnly = 0x100 + } +} diff --git a/Projects/UOContent/Items/Misc/TrashBarrel.cs b/Projects/UOContent/Items/Misc/TrashBarrel.cs index d79e2fa4b..96bd221ac 100644 --- a/Projects/UOContent/Items/Misc/TrashBarrel.cs +++ b/Projects/UOContent/Items/Misc/TrashBarrel.cs @@ -1,156 +1,127 @@ using System; +using ModernUO.Serialization; using Server.Multis; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class TrashBarrel : Container, IChoppable { - public class TrashBarrel : Container, IChoppable + private Timer m_Timer; + + [Constructible] + public TrashBarrel() : base(0xE77) { - private Timer m_Timer; + Hue = 0x3B2; + Movable = false; + } - [Constructible] - public TrashBarrel() : base(0xE77) + public override int LabelNumber => 1041064; // a trash barrel + + public override int DefaultMaxWeight => 0; // A value of 0 signals unlimited weight + + public override bool IsDecoContainer => false; + + public void OnChop(Mobile from) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsCoOwner(from) == true) { - Hue = 0x3B2; - Movable = false; + Effects.PlaySound(Location, Map, 0x3B3); + from.SendLocalizedMessage(500461); // You destroy the item. + Destroy(); } + } - public TrashBarrel(Serial serial) : base(serial) + [AfterDeserialization] + private void AfterDeserialization() + { + if (Items.Count > 0) { + m_Timer = new EmptyTimer(this); + m_Timer.Start(); } + } - public override int LabelNumber => 1041064; // a trash barrel - - public override int DefaultMaxWeight => 0; // A value of 0 signals unlimited weight - - public override bool IsDecoContainer => false; - - public void OnChop(Mobile from) + private void InvalidateContents(Mobile from) + { + if (TotalItems >= 50) { - var house = BaseHouse.FindHouseAt(from); + Empty(501478); // The trash is full! Emptying! + } + else + { + SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes - if (house?.IsCoOwner(from) == true) + if (m_Timer != null) { - Effects.PlaySound(Location, Map, 0x3B3); - from.SendLocalizedMessage(500461); // You destroy the item. - Destroy(); + m_Timer.Stop(); } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Items.Count > 0) + else { m_Timer = new EmptyTimer(this); - m_Timer.Start(); } + + m_Timer.Start(); } + } - public override bool OnDragDrop(Mobile from, Item dropped) + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (base.OnDragDrop(from, dropped)) { - if (!base.OnDragDrop(from, dropped)) - { - return false; - } - - if (TotalItems >= 50) - { - Empty(501478); // The trash is full! Emptying! - } - else - { - SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes - - if (m_Timer != null) - { - m_Timer.Stop(); - } - else - { - m_Timer = new EmptyTimer(this); - } - - m_Timer.Start(); - } - + InvalidateContents(from); return true; } - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + return false; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (base.OnDragDropInto(from, item, p)) { - if (!base.OnDragDropInto(from, item, p)) - { - return false; - } - - if (TotalItems >= 50) - { - Empty(501478); // The trash is full! Emptying! - } - else - { - SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes - - if (m_Timer != null) - { - m_Timer.Stop(); - } - else - { - m_Timer = new EmptyTimer(this); - } - - m_Timer.Start(); - } - + InvalidateContents(from); return true; } - public void Empty(int message) + return false; + } + + public void Empty(int message) + { + var items = Items; + + if (items.Count > 0) { - var items = Items; + PublicOverheadMessage(MessageType.Regular, 0x3B2, message); - if (items.Count > 0) + for (var i = items.Count - 1; i >= 0; --i) { - PublicOverheadMessage(MessageType.Regular, 0x3B2, message); - - for (var i = items.Count - 1; i >= 0; --i) + if (i >= items.Count) { - if (i >= items.Count) - { - continue; - } - - items[i].Delete(); + continue; } + + items[i].Delete(); } - - m_Timer?.Stop(); - - m_Timer = null; } - private class EmptyTimer : Timer + m_Timer?.Stop(); + m_Timer = null; + } + + private class EmptyTimer : Timer + { + private TrashBarrel _barrel; + + public EmptyTimer(TrashBarrel barrel) : base(TimeSpan.FromMinutes(3.0)) => _barrel = barrel; + + protected override void OnTick() { - private readonly TrashBarrel m_Barrel; - - public EmptyTimer(TrashBarrel barrel) : base(TimeSpan.FromMinutes(3.0)) => m_Barrel = barrel; - - protected override void OnTick() - { - m_Barrel.Empty(501479); // Emptying the trashcan! - } + _barrel.Empty(501479); // Emptying the trashcan! } } } diff --git a/Projects/UOContent/Items/Misc/TrashChest.cs b/Projects/UOContent/Items/Misc/TrashChest.cs index c6ee92d55..fa3fec8a1 100644 --- a/Projects/UOContent/Items/Misc/TrashChest.cs +++ b/Projects/UOContent/Items/Misc/TrashChest.cs @@ -1,59 +1,40 @@ +using ModernUO.Serialization; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[Flippable(0xE41, 0xE40)] +[SerializationGenerator(0, false)] +public partial class TrashChest : Container { - [Flippable(0xE41, 0xE40)] - public class TrashChest : Container + [Constructible] + public TrashChest() : base(0xE41) => Movable = false; + + public override int DefaultMaxWeight => 0; // A value of 0 signals unlimited weight + + public override bool IsDecoContainer => false; + + public override bool OnDragDrop(Mobile from, Item dropped) { - [Constructible] - public TrashChest() : base(0xE41) => Movable = false; - - public TrashChest(Serial serial) : base(serial) + if (base.OnDragDrop(from, dropped)) { - } - - public override int DefaultMaxWeight => 0; // A value of 0 signals unlimited weight - - public override bool IsDecoContainer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (!base.OnDragDrop(from, dropped)) - { - return false; - } - PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1042891, 8)); dropped.Delete(); - return true; } - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (!base.OnDragDropInto(from, item, p)) - { - return false; - } + return false; + } + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (base.OnDragDropInto(from, item, p)) + { PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1042891, 8)); item.Delete(); - return true; } + + return false; } } diff --git a/Projects/UOContent/Items/Misc/TribalBerry.cs b/Projects/UOContent/Items/Misc/TribalBerry.cs index e309d5a9f..4d6f1eb8a 100644 --- a/Projects/UOContent/Items/Misc/TribalBerry.cs +++ b/Projects/UOContent/Items/Misc/TribalBerry.cs @@ -1,39 +1,18 @@ -namespace Server.Items +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class TribalBerry : Item { - public class TribalBerry : Item + [Constructible] + public TribalBerry(int amount = 1) : base(0x9D0) { - [Constructible] - public TribalBerry(int amount = 1) : base(0x9D0) - { - Weight = 1.0; - Stackable = true; - Amount = amount; - Hue = 6; - } - - public TribalBerry(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1040001; // tribal berry - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - if (Hue == 4) - { - Hue = 6; - } - } + Weight = 1.0; + Stackable = true; + Amount = amount; + Hue = 6; } + + public override int LabelNumber => 1040001; // tribal berry } diff --git a/Projects/UOContent/Items/Misc/TribalPaint.cs b/Projects/UOContent/Items/Misc/TribalPaint.cs index ee8cdfad6..8bad846bb 100644 --- a/Projects/UOContent/Items/Misc/TribalPaint.cs +++ b/Projects/UOContent/Items/Misc/TribalPaint.cs @@ -1,4 +1,5 @@ using System; +using ModernUO.Serialization; using Server.Factions; using Server.Mobiles; using Server.Spells; @@ -6,87 +7,67 @@ using Server.Spells.Fifth; using Server.Spells.Ninjitsu; using Server.Spells.Seventh; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class TribalPaint : Item { - public class TribalPaint : Item + [Constructible] + public TribalPaint() : base(0x9EC) { - [Constructible] - public TribalPaint() : base(0x9EC) + Hue = 2101; + Weight = 2.0; + Stackable = Core.ML; + } + + public override int LabelNumber => 1040000; // savage kin paint + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { - Hue = 2101; - Weight = 2.0; - Stackable = Core.ML; + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; } - public TribalPaint(Serial serial) : base(serial) + if (Sigil.ExistsOn(from)) { + from.SendLocalizedMessage(1010465); // You cannot disguise yourself while holding a sigil. } - - public override int LabelNumber => 1040000; // savage kin paint - - public override void OnDoubleClick(Mobile from) + else if (!from.CanBeginAction()) { - if (IsChildOf(from.Backpack)) + from.SendLocalizedMessage(501698); // You cannot disguise yourself while incognitoed. + } + else if (!from.CanBeginAction()) + { + from.SendLocalizedMessage(501699); // You cannot disguise yourself while polymorphed. + } + else if (TransformationSpellHelper.UnderTransformation(from)) + { + from.SendLocalizedMessage(501699); // You cannot disguise yourself while polymorphed. + } + else if (AnimalForm.UnderTransformation(from)) + { + from.SendLocalizedMessage(1061634); // You cannot disguise yourself while in that form. + } + else if (from.IsBodyMod || from.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + { + from.SendLocalizedMessage(501605); // You are already disguised. + } + else + { + from.BodyMod = from.Female ? 184 : 183; + from.HueMod = 0; + + if (from is PlayerMobile mobile) { - if (Sigil.ExistsOn(from)) - { - from.SendLocalizedMessage(1010465); // You cannot disguise yourself while holding a sigil. - } - else if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(501698); // You cannot disguise yourself while incognitoed. - } - else if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(501699); // You cannot disguise yourself while polymorphed. - } - else if (TransformationSpellHelper.UnderTransformation(from)) - { - from.SendLocalizedMessage(501699); // You cannot disguise yourself while polymorphed. - } - else if (AnimalForm.UnderTransformation(from)) - { - from.SendLocalizedMessage(1061634); // You cannot disguise yourself while in that form. - } - else if (from.IsBodyMod || from.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - { - from.SendLocalizedMessage(501605); // You are already disguised. - } - else - { - from.BodyMod = from.Female ? 184 : 183; - from.HueMod = 0; - - if (from is PlayerMobile mobile) - { - mobile.SavagePaintExpiration = TimeSpan.FromDays(7.0); - } - - from.SendLocalizedMessage( - 1042537 - ); // You now bear the markings of the savage tribe. Your body paint will last about a week or you can remove it with an oil cloth. - - Consume(); - } + mobile.SavagePaintExpiration = TimeSpan.FromDays(7.0); } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + // You now bear the markings of the savage tribe. Your body paint will last about a week or you can remove it with an oil cloth. + from.SendLocalizedMessage(1042537); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); + Consume(); } } } diff --git a/Projects/UOContent/Items/Misc/UnholyBone.cs b/Projects/UOContent/Items/Misc/UnholyBone.cs index 0c5101d99..147342ee4 100644 --- a/Projects/UOContent/Items/Misc/UnholyBone.cs +++ b/Projects/UOContent/Items/Misc/UnholyBone.cs @@ -1,116 +1,100 @@ using System; +using ModernUO.Serialization; using Server.Mobiles; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public partial class UnholyBone : Item, ICarvable { - public class UnholyBone : Item, ICarvable + private SpawnTimer m_Timer; + + [Constructible] + public UnholyBone() : base(0xF7E) { - private SpawnTimer m_Timer; + Movable = false; + Hue = 0x497; - [Constructible] - public UnholyBone() : base(0xF7E) + m_Timer = new SpawnTimer(this); + m_Timer.Start(); + } + + public override string DefaultName => "unholy bone"; + + public void Carve(Mobile from, Item item) + { + Effects.PlaySound(GetWorldLocation(), Map, 0x48F); + Effects.SendLocationEffect(GetWorldLocation(), Map, 0x3728, 10); + + if (Utility.RandomDouble() < 0.3) { - Movable = false; - Hue = 0x497; - - m_Timer = new SpawnTimer(this); - m_Timer.Start(); - } - - public UnholyBone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "unholy bone"; - - public void Carve(Mobile from, Item item) - { - Effects.PlaySound(GetWorldLocation(), Map, 0x48F); - Effects.SendLocationEffect(GetWorldLocation(), Map, 0x3728, 10); - - if (Utility.RandomDouble() < 0.3) + if (ItemID == 0xF7E) { - if (ItemID == 0xF7E) - { - from.SendMessage("You destroy the bone."); - } - else - { - from.SendMessage("You destroy the bone pile."); - } - - var gold = new Gold(25, 100); - - gold.MoveToWorld(GetWorldLocation(), Map); - - Delete(); - - m_Timer.Stop(); + from.SendMessage("You destroy the bone."); } else { - if (ItemID == 0xF7E) - { - from.SendMessage("You damage the bone."); - } - else - { - from.SendMessage("You damage the bone pile."); - } + from.SendMessage("You destroy the bone pile."); } + + var gold = new Gold(25, 100); + + gold.MoveToWorld(GetWorldLocation(), Map); + + Delete(); + + m_Timer.Stop(); } - - public override void Serialize(IGenericWriter writer) + else if (ItemID == 0xF7E) { - base.Serialize(writer); - - writer.Write(0); // version + from.SendMessage("You damage the bone."); } - - public override void Deserialize(IGenericReader reader) + else { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - m_Timer = new SpawnTimer(this); - m_Timer.Start(); + from.SendMessage("You damage the bone pile."); } + } - private class SpawnTimer : Timer + [AfterDeserialization] + private void AfterDeserialize() + { + m_Timer = new SpawnTimer(this); + m_Timer.Start(); + } + + private class SpawnTimer : Timer + { + private Item m_Item; + + public SpawnTimer(Item item) : base(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10))) => m_Item = item; + + protected override void OnTick() { - private readonly Item m_Item; - - public SpawnTimer(Item item) : base(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10))) => m_Item = item; - - protected override void OnTick() + if (m_Item?.Deleted != false) { - if (m_Item.Deleted) - { - return; - } - - var spawn = Utility.Random(12) switch - { - 0 => (Mobile)new Skeleton(), - 1 => new Zombie(), - 2 => new Wraith(), - 3 => new Spectre(), - 4 => new Ghoul(), - 5 => new Mummy(), - 6 => new Bogle(), - 7 => new RottingCorpse(), - 8 => new BoneKnight(), - 9 => new SkeletalKnight(), - 10 => new Lich(), - 11 => new LichLord(), - _ => new Skeleton() - }; - - spawn.MoveToWorld(m_Item.Location, m_Item.Map); - - m_Item.Delete(); + return; } + + Mobile spawn = Utility.Random(12) switch + { + 0 => new Skeleton(), + 1 => new Zombie(), + 2 => new Wraith(), + 3 => new Spectre(), + 4 => new Ghoul(), + 5 => new Mummy(), + 6 => new Bogle(), + 7 => new RottingCorpse(), + 8 => new BoneKnight(), + 9 => new SkeletalKnight(), + 10 => new Lich(), + 11 => new LichLord(), + _ => new Skeleton() + }; + + spawn.MoveToWorld(m_Item.Location, m_Item.Map); + + m_Item.Delete(); } } } diff --git a/Projects/UOContent/Items/Misc/WarningItem.cs b/Projects/UOContent/Items/Misc/WarningItem.cs index 8d7c9e8ab..85cd73954 100644 --- a/Projects/UOContent/Items/Misc/WarningItem.cs +++ b/Projects/UOContent/Items/Misc/WarningItem.cs @@ -1,237 +1,162 @@ using System; using System.Collections.Generic; +using ModernUO.Serialization; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(1, false)] +public partial class WarningItem : Item { - public class WarningItem : Item + private bool m_Broadcasting; + + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TextDefinition _warningMessage; + + // Field 1 + private int _range; + + [SerializableField(2)] + private TimeSpan _resetDelay; + + private DateTime m_LastBroadcast; + + [Constructible] + public WarningItem(int itemID, int range, int warning) : base(itemID) { - private bool m_Broadcasting; + Movable = false; - private DateTime m_LastBroadcast; - private int m_Range; + _warningMessage = warning; + _range = Math.Min(range, 18); + } - [Constructible] - public WarningItem(int itemID, int range, int warning) : base(itemID) + [Constructible] + public WarningItem(int itemID, int range, string warning) : base(itemID) + { + Movable = false; + + _warningMessage = warning; + _range = Math.Min(range, 18); + } + + [CommandProperty(AccessLevel.GameMaster)] + [SerializableProperty(1, useField: nameof(_range))] + public int Range + { + get => _range; + set { - if (range > 18) - { - range = 18; - } - - Movable = false; - - WarningNumber = warning; - m_Range = range; - } - - [Constructible] - public WarningItem(int itemID, int range, string warning) : base(itemID) - { - if (range > 18) - { - range = 18; - } - - Movable = false; - - WarningString = warning; - m_Range = range; - } - - public WarningItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string WarningString { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int WarningNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Range - { - get => m_Range; - set - { - if (value > 18) - { - value = 18; - } - - m_Range = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan ResetDelay { get; set; } - - public virtual bool OnlyToTriggerer => false; - public virtual int NeighborRange => 5; - - public override bool HandlesOnMovement => true; - - public virtual void SendMessage(Mobile triggerer, bool onlyToTriggerer, string messageString, int messageNumber) - { - if (onlyToTriggerer) - { - if (messageString != null) - { - triggerer.SendMessage(messageString); - } - else - { - triggerer.SendLocalizedMessage(messageNumber); - } - } - else - { - if (messageString != null) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, false, messageString); - } - else - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, messageNumber); - } - } - } - - public virtual void Broadcast(Mobile triggerer) - { - if (m_Broadcasting || Core.Now < m_LastBroadcast + ResetDelay) - { - return; - } - - m_LastBroadcast = Core.Now; - - m_Broadcasting = true; - - SendMessage(triggerer, OnlyToTriggerer, WarningString, WarningNumber); - - if (NeighborRange >= 0) - { - var list = new List(); - - foreach (var item in GetItemsInRange(NeighborRange)) - { - if (item != this && item is WarningItem warningItem) - { - list.Add(warningItem); - } - } - - for (var i = 0; i < list.Count; i++) - { - list[i].Broadcast(triggerer); - } - } - - Timer.StartTimer(StopBroadcasting); - } - - private void StopBroadcasting() - { - m_Broadcasting = false; - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m.Player && Utility.InRange(m.Location, Location, m_Range) && - !Utility.InRange(oldLocation, Location, m_Range)) - { - Broadcast(m); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(WarningString); - writer.Write(WarningNumber); - writer.Write(m_Range); - - writer.Write(ResetDelay); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - WarningString = reader.ReadString(); - WarningNumber = reader.ReadInt(); - m_Range = reader.ReadInt(); - ResetDelay = reader.ReadTimeSpan(); - - break; - } - } + _range = Math.Min(value, 18); + this.MarkDirty(); } } - public class HintItem : WarningItem + public virtual bool OnlyToTriggerer => false; + public virtual int NeighborRange => 5; + + public override bool HandlesOnMovement => true; + + public virtual void SendMessage(Mobile triggerer, bool onlyToTriggerer, TextDefinition warningMessage) { - [Constructible] - public HintItem(int itemID, int range, int warning, int hint) : base(itemID, range, warning) => HintNumber = hint; - - [Constructible] - public HintItem(int itemID, int range, string warning, string hint) : base(itemID, range, warning) => - HintString = hint; - - public HintItem(Serial serial) : base(serial) + if (onlyToTriggerer) { + warningMessage.SendMessageTo(triggerer); + } + else + { + warningMessage.PublicOverheadMessage(this, MessageType.Regular, 0x3B2); + } + } + + public virtual void Broadcast(Mobile triggerer) + { + if (m_Broadcasting || Core.Now < m_LastBroadcast + ResetDelay) + { + return; } - [CommandProperty(AccessLevel.GameMaster)] - public string HintString { get; set; } + m_LastBroadcast = Core.Now; - [CommandProperty(AccessLevel.GameMaster)] - public int HintNumber { get; set; } + m_Broadcasting = true; - public override bool OnlyToTriggerer => true; + SendMessage(triggerer, OnlyToTriggerer, _warningMessage); - public override void OnDoubleClick(Mobile from) + if (NeighborRange >= 0) { - SendMessage(from, true, HintString, HintNumber); - } + var list = new List(); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(HintString); - writer.Write(HintNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) + foreach (var item in GetItemsInRange(NeighborRange)) { - case 0: - { - HintString = reader.ReadString(); - HintNumber = reader.ReadInt(); + if (item != this && item is WarningItem warningItem) + { + list.Add(warningItem); + } + } - break; - } + for (var i = 0; i < list.Count; i++) + { + list[i].Broadcast(triggerer); } } + + Timer.StartTimer(StopBroadcasting); + } + + private void StopBroadcasting() + { + m_Broadcasting = false; + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Player && Utility.InRange(m.Location, Location, _range) && + !Utility.InRange(oldLocation, Location, _range)) + { + Broadcast(m); + } + } + + public void Deserialize(IGenericReader reader, int version) + { + var warningMessageString = reader.ReadString(); + var warningMessageInt = reader.ReadInt(); + + _range = reader.ReadInt(); + ResetDelay = reader.ReadTimeSpan(); + + _warningMessage = warningMessageInt > 0 ? warningMessageInt : warningMessageString; + } +} + + +[SerializationGenerator(1, false)] +public partial class HintItem : WarningItem +{ + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private TextDefinition _hintMessage; + + [Constructible] + public HintItem(int itemID, int range, int warning, int hint) : base(itemID, range, warning) => + _hintMessage = hint; + + [Constructible] + public HintItem(int itemID, int range, string warning, string hint) : base(itemID, range, warning) => + _hintMessage = hint; + + public override bool OnlyToTriggerer => true; + + public override void OnDoubleClick(Mobile from) + { + SendMessage(from, true, _hintMessage); + } + + private void Deserialize(IGenericReader reader, int version) + { + var hintMessageString = reader.ReadString(); + var hintMessageInt = reader.ReadInt(); + + _hintMessage = hintMessageInt > 0 ? hintMessageInt : hintMessageString; } } diff --git a/Projects/UOContent/Items/Misc/WayPoint.cs b/Projects/UOContent/Items/Misc/WayPoint.cs index 1836fb29b..b00c8f1a5 100644 --- a/Projects/UOContent/Items/Misc/WayPoint.cs +++ b/Projects/UOContent/Items/Misc/WayPoint.cs @@ -1,155 +1,116 @@ +using ModernUO.Serialization; using Server.Targeting; -namespace Server.Items +namespace Server.Items; + +[Flippable(0x1f14, 0x1f15, 0x1f16, 0x1f17)] +[SerializationGenerator(0, false)] +public partial class WayPoint : Item { - [Flippable(0x1f14, 0x1f15, 0x1f16, 0x1f17)] - public class WayPoint : Item + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private WayPoint _nextPoint; + + [Constructible] + public WayPoint(WayPoint prev = null) : base(0x1f14) { - private WayPoint m_Next; + Hue = 0x498; + Visible = false; + // this.Movable = false; - [Constructible] - public WayPoint(WayPoint prev = null) : base(0x1f14) + if (prev != null) { - Hue = 0x498; - Visible = false; - // this.Movable = false; - - if (prev != null) - { - prev.NextPoint = this; - } - } - - public WayPoint(Serial serial) : base(serial) - { - } - - public override string DefaultName => "AI Way Point"; - - [CommandProperty(AccessLevel.GameMaster)] - public WayPoint NextPoint - { - get => m_Next; - set - { - if (m_Next != this) - { - m_Next = value; - } - } - } - - public static void Initialize() - { - CommandSystem.Register("WayPointSeq", AccessLevel.GameMaster, WayPointSeq_OnCommand); - } - - public static void WayPointSeq_OnCommand(CommandEventArgs arg) - { - arg.Mobile.SendMessage("Target the position of the first way point."); - arg.Mobile.Target = new WayPointSeqTarget(null); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - { - from.SendMessage("Target the next way point in the sequence."); - - from.Target = new NextPointTarget(this); - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (m_Next == null) - { - LabelTo(from, "(Unlinked)"); - } - else - { - LabelTo(from, "(Linked: {0})", m_Next.Location); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Next = reader.ReadEntity(); - break; - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_Next); + prev.NextPoint = this; } } - public class NextPointTarget : Target + public override string DefaultName => "AI Way Point"; + + public static void Initialize() { - private readonly WayPoint m_Point; + CommandSystem.Register("WayPointSeq", AccessLevel.GameMaster, WayPointSeq_OnCommand); + } - public NextPointTarget(WayPoint pt) : base(-1, false, TargetFlags.None) => m_Point = pt; + public static void WayPointSeq_OnCommand(CommandEventArgs arg) + { + arg.Mobile.SendMessage("Target the position of the first way point."); + arg.Mobile.Target = new WayPointSeqTarget(null); + } - protected override void OnTarget(Mobile from, object target) + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) { - if (target is WayPoint point && m_Point != null) - { - m_Point.NextPoint = point; - } - else - { - from.SendMessage("Target a way point."); - } + from.SendMessage("Target the next way point in the sequence."); + + from.Target = new NextPointTarget(this); } } - public class WayPointSeqTarget : Target + public override void OnSingleClick(Mobile from) { - private readonly WayPoint m_Last; + base.OnSingleClick(from); - public WayPointSeqTarget(WayPoint last) : base(-1, true, TargetFlags.None) => m_Last = last; - - protected override void OnTarget(Mobile from, object targeted) + if (_nextPoint == null) { - if (targeted is WayPoint wayPoint) - { - if (m_Last != null) - { - m_Last.NextPoint = wayPoint; - } - } - else if (targeted is IPoint3D d) - { - var p = new Point3D(d); - - var point = new WayPoint(m_Last); - point.MoveToWorld(p, from.Map); - - from.Target = new WayPointSeqTarget(point); - from.SendMessage( - "Target the position of the next way point in the sequence, or target a way point link the newest way point to." - ); - } - else - { - from.SendMessage("Target a position, or another way point."); - } + LabelTo(from, "(Unlinked)"); + } + else + { + LabelTo(from, "(Linked: {0})", _nextPoint.Location); + } + } +} + +public class NextPointTarget : Target +{ + private WayPoint _point; + + public NextPointTarget(WayPoint pt) : base(-1, false, TargetFlags.None) => _point = pt; + + protected override void OnTarget(Mobile from, object target) + { + if (target is WayPoint point && _point != null) + { + _point.NextPoint = point; + } + else + { + from.SendMessage("Target a way point."); + } + } +} + +public class WayPointSeqTarget : Target +{ + private WayPoint _last; + + public WayPointSeqTarget(WayPoint last) : base(-1, true, TargetFlags.None) => _last = last; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is WayPoint wayPoint) + { + if (_last != null) + { + _last.NextPoint = wayPoint; + } + } + else if (targeted is IPoint3D d) + { + var p = new Point3D(d); + + var point = new WayPoint(_last); + point.MoveToWorld(p, from.Map); + + from.Target = new WayPointSeqTarget(point); + from.SendMessage( + "Target the position of the next way point in the sequence, or target a way point link the newest way point to." + ); + } + else + { + from.SendMessage("Target a position, or another way point."); } } } diff --git a/Projects/UOContent/Items/Misc/WindChimes.cs b/Projects/UOContent/Items/Misc/WindChimes.cs index 6e1d5e0ef..88471997d 100644 --- a/Projects/UOContent/Items/Misc/WindChimes.cs +++ b/Projects/UOContent/Items/Misc/WindChimes.cs @@ -1,188 +1,120 @@ +using ModernUO.Serialization; using Server.Gumps; using Server.Multis; using Server.Network; -namespace Server.Items +namespace Server.Items; + +[SerializationGenerator(0, false)] +public abstract partial class BaseWindChimes : Item { - public abstract class BaseWindChimes : Item + [InvalidateProperties] + [SerializableField(0)] + [SerializableFieldAttr("[CommandProperty(AccessLevel.GameMaster)]")] + private bool _turnedOn; + + public BaseWindChimes(int itemID) : base(itemID) { - private bool m_TurnedOn; + } - public BaseWindChimes(int itemID) : base(itemID) + public static int[] Sounds { get; } = { 0x505, 0x506, 0x507 }; + + public override bool HandlesOnMovement => _turnedOn && IsLockedDown; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (_turnedOn && IsLockedDown && (!m.Hidden || m.AccessLevel == AccessLevel.Player) && + Utility.InRange(m.Location, Location, 2) && !Utility.InRange(oldLocation, Location, 2)) { + Effects.PlaySound(Location, Map, Sounds.RandomElement()); } - public BaseWindChimes(Serial serial) : base(serial) + base.OnMovement(m, oldLocation); + } + + public override void GetProperties(IPropertyList list) + { + base.GetProperties(list); + + if (_turnedOn) { + list.Add(502695); // turned on } - - [CommandProperty(AccessLevel.GameMaster)] - public bool TurnedOn + else { - get => m_TurnedOn; - set - { - m_TurnedOn = value; - InvalidateProperties(); - } - } - - public static int[] Sounds { get; } = { 0x505, 0x506, 0x507 }; - - public override bool HandlesOnMovement => m_TurnedOn && IsLockedDown; - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m_TurnedOn && IsLockedDown && (!m.Hidden || m.AccessLevel == AccessLevel.Player) && - Utility.InRange(m.Location, Location, 2) && !Utility.InRange(oldLocation, Location, 2)) - { - Effects.PlaySound(Location, Map, Sounds.RandomElement()); - } - - base.OnMovement(m, oldLocation); - } - - public override void GetProperties(IPropertyList list) - { - base.GetProperties(list); - - if (m_TurnedOn) - { - list.Add(502695); // turned on - } - else - { - list.Add(502696); // turned off - } - } - - public bool IsOwner(Mobile mob) => BaseHouse.FindHouseAt(this)?.IsOwner(mob) == true; - - public override void OnDoubleClick(Mobile from) - { - if (IsOwner(from)) - { - from.SendGump(new OnOffGump(this)); - } - else - { - from.SendLocalizedMessage(502691); // You must be the owner to use this. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_TurnedOn); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - var version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_TurnedOn = reader.ReadBool(); - break; - } - } - } - - private class OnOffGump : Gump - { - private readonly BaseWindChimes m_Chimes; - - public OnOffGump(BaseWindChimes chimes) : base(150, 200) - { - m_Chimes = chimes; - - AddBackground(0, 0, 300, 150, 0xA28); - AddHtmlLocalized(45, 20, 300, 35, chimes.TurnedOn ? 1011035 : 1011034); // [De]Activate this item - AddButton(40, 53, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(80, 55, 65, 35, 1011036); // OKAY - AddButton(150, 53, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(190, 55, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - var from = sender.Mobile; - - if (info.ButtonID == 1) - { - var newValue = !m_Chimes.TurnedOn; - - m_Chimes.TurnedOn = newValue; - - if (newValue && !m_Chimes.IsLockedDown) - { - from.SendLocalizedMessage(502693); // Remember, this only works when locked down. - } - } - else - { - from.SendLocalizedMessage(502694); // Cancelled action. - } - } + list.Add(502696); // turned off } } - public class WindChimes : BaseWindChimes + public bool IsOwner(Mobile mob) => BaseHouse.FindHouseAt(this)?.IsOwner(mob) == true; + + public override void OnDoubleClick(Mobile from) { - [Constructible] - public WindChimes() : base(0x2832) + if (IsOwner(from)) { + from.SendGump(new OnOffGump(this)); } - - public WindChimes(Serial serial) : base(serial) + else { - } - - public override int LabelNumber => 1030290; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - var version = reader.ReadInt(); + from.SendLocalizedMessage(502691); // You must be the owner to use this. } } - public class FancyWindChimes : BaseWindChimes + private class OnOffGump : Gump { - [Constructible] - public FancyWindChimes() : base(0x2833) + private readonly BaseWindChimes m_Chimes; + + public OnOffGump(BaseWindChimes chimes) : base(150, 200) { + m_Chimes = chimes; + + AddBackground(0, 0, 300, 150, 0xA28); + AddHtmlLocalized(45, 20, 300, 35, chimes.TurnedOn ? 1011035 : 1011034); // [De]Activate this item + AddButton(40, 53, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(80, 55, 65, 35, 1011036); // OKAY + AddButton(150, 53, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(190, 55, 100, 35, 1011012); // CANCEL } - public FancyWindChimes(Serial serial) : base(serial) + public override void OnResponse(NetState sender, RelayInfo info) { - } + var from = sender.Mobile; - public override int LabelNumber => 1030291; + if (info.ButtonID == 1) + { + var newValue = !m_Chimes.TurnedOn; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } + m_Chimes.TurnedOn = newValue; - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - var version = reader.ReadInt(); + if (newValue && !m_Chimes.IsLockedDown) + { + from.SendLocalizedMessage(502693); // Remember, this only works when locked down. + } + } + else + { + from.SendLocalizedMessage(502694); // Cancelled action. + } } } } + +[SerializationGenerator(0, false)] +public partial class WindChimes : BaseWindChimes +{ + [Constructible] + public WindChimes() : base(0x2832) + { + } +} + +[SerializationGenerator(0, false)] +public partial class FancyWindChimes : BaseWindChimes +{ + [Constructible] + public FancyWindChimes() : base(0x2833) + { + } + + public override int LabelNumber => 1030291; +} diff --git a/Projects/UOContent/Migrations/Server.Items.BaseWindChimes.v0.json b/Projects/UOContent/Migrations/Server.Items.BaseWindChimes.v0.json new file mode 100644 index 000000000..bc9f55711 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.BaseWindChimes.v0.json @@ -0,0 +1,14 @@ +{ + "version": 0, + "type": "Server.Items.BaseWindChimes", + "properties": [ + { + "name": "TurnedOn", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.ControlPanel.v1.json b/Projects/UOContent/Migrations/Server.Items.ControlPanel.v1.json new file mode 100644 index 000000000..0d70efa1e --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.ControlPanel.v1.json @@ -0,0 +1,24 @@ +{ + "version": 1, + "type": "Server.Items.ControlPanel", + "properties": [ + { + "name": "SideLength", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Path", + "type": "Server.Point2D[]", + "rule": "ArrayMigrationRule", + "ruleArguments": [ + "Server.Point2D", + "PrimitiveUOTypeMigrationRule", + "Point2D" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.FancyWindChimes.v0.json b/Projects/UOContent/Migrations/Server.Items.FancyWindChimes.v0.json new file mode 100644 index 000000000..8c28a714c --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.FancyWindChimes.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.FancyWindChimes" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.HintItem.v1.json b/Projects/UOContent/Migrations/Server.Items.HintItem.v1.json new file mode 100644 index 000000000..8ea41fa4b --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.HintItem.v1.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "type": "Server.Items.HintItem", + "properties": [ + { + "name": "HintMessage", + "type": "Server.TextDefinition", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "TextDefinition" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.KeywordTeleporter.v0.json b/Projects/UOContent/Migrations/Server.Items.KeywordTeleporter.v0.json new file mode 100644 index 000000000..46acb0127 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.KeywordTeleporter.v0.json @@ -0,0 +1,30 @@ +{ + "version": 0, + "type": "Server.Items.KeywordTeleporter", + "properties": [ + { + "name": "Substring", + "type": "string", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Keyword", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Range", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.LocalizedStatic.v0.json b/Projects/UOContent/Migrations/Server.Items.LocalizedStatic.v0.json new file mode 100644 index 000000000..d8dd6aeaa --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.LocalizedStatic.v0.json @@ -0,0 +1,14 @@ +{ + "version": 0, + "type": "Server.Items.LocalizedStatic", + "properties": [ + { + "name": "Number", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "EncodedInt" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.PowerGenerator.v0.json b/Projects/UOContent/Migrations/Server.Items.PowerGenerator.v0.json new file mode 100644 index 000000000..ef4a2e515 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.PowerGenerator.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.PowerGenerator" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Scales.v0.json b/Projects/UOContent/Migrations/Server.Items.Scales.v0.json new file mode 100644 index 000000000..636fc5c4c --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Scales.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Scales" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SerpentPillar.v0.json b/Projects/UOContent/Migrations/Server.Items.SerpentPillar.v0.json new file mode 100644 index 000000000..08211e45d --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SerpentPillar.v0.json @@ -0,0 +1,30 @@ +{ + "version": 0, + "type": "Server.Items.SerpentPillar", + "properties": [ + { + "name": "Active", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Word", + "type": "string", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Destination", + "type": "Server.Rectangle2D", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Rect2D" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SkillTeleporter.v1.json b/Projects/UOContent/Migrations/Server.Items.SkillTeleporter.v1.json new file mode 100644 index 000000000..2c5d57325 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SkillTeleporter.v1.json @@ -0,0 +1,28 @@ +{ + "version": 1, + "type": "Server.Items.SkillTeleporter", + "properties": [ + { + "name": "Skill", + "type": "Server.SkillName", + "rule": "EnumMigrationRule" + }, + { + "name": "Required", + "type": "double", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "Message", + "type": "Server.TextDefinition", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "@CanBeNull", + "TextDefinition" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SpecialBeardDye.v0.json b/Projects/UOContent/Migrations/Server.Items.SpecialBeardDye.v0.json new file mode 100644 index 000000000..09278cb58 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SpecialBeardDye.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.SpecialBeardDye" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SpecialHairDye.v0.json b/Projects/UOContent/Migrations/Server.Items.SpecialHairDye.v0.json new file mode 100644 index 000000000..e60a4c562 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SpecialHairDye.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.SpecialHairDye" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Static.v0.json b/Projects/UOContent/Migrations/Server.Items.Static.v0.json new file mode 100644 index 000000000..b15965728 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Static.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.Static" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.SwarmOfFlies.v0.json b/Projects/UOContent/Migrations/Server.Items.SwarmOfFlies.v0.json new file mode 100644 index 000000000..dcf320b74 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.SwarmOfFlies.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.SwarmOfFlies" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.Teleporter.v5.json b/Projects/UOContent/Migrations/Server.Items.Teleporter.v5.json new file mode 100644 index 000000000..2ffdb5f82 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.Teleporter.v5.json @@ -0,0 +1,40 @@ +{ + "version": 5, + "type": "Server.Items.Teleporter", + "properties": [ + { + "name": "Flags", + "type": "Server.Items.TeleporterFlags", + "rule": "EnumMigrationRule" + }, + { + "name": "Delay", + "type": "System.TimeSpan", + "rule": "PrimitiveTypeMigrationRule" + }, + { + "name": "SoundID", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "EncodedInt" + ] + }, + { + "name": "PointDest", + "type": "Server.Point3D", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Point3D" + ] + }, + { + "name": "MapDest", + "type": "Server.Map", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "Map" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.TrashBarrel.v0.json b/Projects/UOContent/Migrations/Server.Items.TrashBarrel.v0.json new file mode 100644 index 000000000..9aa801fb9 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.TrashBarrel.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.TrashBarrel" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.TrashChest.v0.json b/Projects/UOContent/Migrations/Server.Items.TrashChest.v0.json new file mode 100644 index 000000000..768e84e7b --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.TrashChest.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.TrashChest" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.TribalBerry.v0.json b/Projects/UOContent/Migrations/Server.Items.TribalBerry.v0.json new file mode 100644 index 000000000..91622114b --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.TribalBerry.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.TribalBerry" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.TribalPaint.v0.json b/Projects/UOContent/Migrations/Server.Items.TribalPaint.v0.json new file mode 100644 index 000000000..c48b42328 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.TribalPaint.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.TribalPaint" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.UnholyBone.v0.json b/Projects/UOContent/Migrations/Server.Items.UnholyBone.v0.json new file mode 100644 index 000000000..a9111fb9f --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.UnholyBone.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.UnholyBone" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.WaitTeleporter.v1.json b/Projects/UOContent/Migrations/Server.Items.WaitTeleporter.v1.json new file mode 100644 index 000000000..b767392e2 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.WaitTeleporter.v1.json @@ -0,0 +1,32 @@ +{ + "version": 1, + "type": "Server.Items.WaitTeleporter", + "properties": [ + { + "name": "StartMessage", + "type": "Server.TextDefinition", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "@CanBeNull", + "TextDefinition" + ] + }, + { + "name": "ProgressMessage", + "type": "Server.TextDefinition", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "@CanBeNull", + "TextDefinition" + ] + }, + { + "name": "ShowTimeRemaining", + "type": "bool", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.WarningItem.v1.json b/Projects/UOContent/Migrations/Server.Items.WarningItem.v1.json new file mode 100644 index 000000000..4d779f832 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.WarningItem.v1.json @@ -0,0 +1,27 @@ +{ + "version": 1, + "type": "Server.Items.WarningItem", + "properties": [ + { + "name": "WarningMessage", + "type": "Server.TextDefinition", + "rule": "PrimitiveUOTypeMigrationRule", + "ruleArguments": [ + "TextDefinition" + ] + }, + { + "name": "Range", + "type": "int", + "rule": "PrimitiveTypeMigrationRule", + "ruleArguments": [ + "" + ] + }, + { + "name": "ResetDelay", + "type": "System.TimeSpan", + "rule": "PrimitiveTypeMigrationRule" + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.WayPoint.v0.json b/Projects/UOContent/Migrations/Server.Items.WayPoint.v0.json new file mode 100644 index 000000000..df65e5961 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.WayPoint.v0.json @@ -0,0 +1,11 @@ +{ + "version": 0, + "type": "Server.Items.WayPoint", + "properties": [ + { + "name": "NextPoint", + "type": "Server.Items.WayPoint", + "rule": "SerializableInterfaceMigrationRule" + } + ] +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.WindChimes.v0.json b/Projects/UOContent/Migrations/Server.Items.WindChimes.v0.json new file mode 100644 index 000000000..2a5fd7537 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.WindChimes.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.WindChimes" +} \ No newline at end of file